diff --git a/.gitattributes b/.gitattributes
index e02a50f0e6e9b6515b6078a68ff9ed39722bb0d6..6b41e9483111166dc31ba8e496ab16eaa565536d 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -109,6 +109,7 @@ src/plugins/e-acsl/examples/ensuresec/**/*.py -check-indent
 
 dune-project header_spec=CEA_LGPL
 dune header_spec=CEA_LGPL
+dune-workspace.* header_spec=CEA_LGPL
 
 config* header_spec=CEA_LGPL
 
@@ -198,8 +199,6 @@ README* header_spec=.ignore
 
 /bin/sed_get_* header_spec=.ignore
 
-/dev/dune-workspace.* header_spec=.ignore
-
 /dev/docker/*.sh header_spec=.ignore
 /dev/docker/Dockerfile header_spec=.ignore
 
@@ -215,6 +214,7 @@ README* header_spec=.ignore
 /doc/MakeLaTeXModern header_spec=.ignore
 /doc/acsl_tutorial_slides/script header_spec=.ignore
 /doc/developer/METADOC.txt header_spec=.ignore
+/doc/developer/dune-workspace.bench header_spec=.ignore
 /doc/developer/examples/**/* header_spec=.ignore
 /doc/developer/tutorial/**/* header_spec=.ignore
 /doc/qualification/testing header_spec=.ignore
@@ -266,7 +266,9 @@ README* header_spec=.ignore
 /share/win32_installer.iss header_spec=.ignore
 /share/win32_manual_installation_step.txt header_spec=.ignore
 /share/compliance/*.json header_spec=.ignore
-
+/share/machdeps/.machdep_*.validated header_spec=.ignore
+/share/machdeps/machdep-schema.yaml header_spec=.ignore
+/share/machdeps/machdep_*.yaml header_spec=.ignore
 /tests/**/* header_spec=.ignore
 
 #######################
diff --git a/.gitignore b/.gitignore
index fccad8e706ba06202443d4e05fd631b2d1543d15..0d9cfe2b2ecfb4a609ee6d1c3a813c24a3756795 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,6 +21,8 @@ frama_c_journal.ml
 /.merlin
 /headers/hdrck
 /headers/hdrck.exe
+/bin/ivette
+.ivette
 
 #build
 /_opam/
@@ -51,6 +53,8 @@ _build
 /tests/crowbar/test_ghost_cfg
 /tests/*/*.opt
 
+/.test-errors.log
+
 /dev/fc-time
 /dev/fc-memuse
 /bin/ocamldep_transitive_closure
@@ -190,12 +194,6 @@ Makefile.plugin.generated
 /src/kernel_internals/parsing/clexer.ml
 /src/kernel_internals/parsing/cparser.ml
 /src/kernel_internals/parsing/cparser.mli
-# /src/plugins/callgraph/cg_viewer.ml
-/src/plugins/gui/debug_manager.ml
-/src/plugins/gui/dgraph_helper.ml
-/src/plugins/gui/GSourceView.ml
-/src/plugins/gui/GSourceView.mli
-/src/plugins/gui/gtk_compat.ml
 /src/plugins/markdown-report/META
 
 # generated tar.gz files
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 2b3f95777cc993fbea6088cf52928c941a60c56c..b93b0d75b691d863742a01e4f0f1c2d1baee15b8 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -122,7 +122,7 @@ ivette:
     - node --version
     - npm --version
     - yarn --version
-    - make -C ivette
+    - make -C ivette check-lint dome-app
   tags:
     - docker
 
@@ -139,6 +139,12 @@ e-acsl-tests:
   script:
     - ./nix/build-proxy.sh e-acsl-tests
 
+e-acsl-dev-tests:
+  stage: tests
+  script:
+    - ./nix/build-proxy.sh e-acsl-dev-tests
+  allow_failure: true
+
 .build_template: &eva_template
   stage: tests
   script:
@@ -216,6 +222,7 @@ external-plugins:
           "meta",
           "minimal",
           "mthread",
+          "pathcrawler",
           "security",
           "volatile"
         ]
diff --git a/Changelog b/Changelog
index 1616be29fd88fbe3a00b8b10f78281cd18a8f76c..e619fceeedb77c384c4a7f965b2de3e7359104ff 100644
--- a/Changelog
+++ b/Changelog
@@ -14,23 +14,60 @@
 # '#?nnn'  : OLD-BTS entry #nnn                                               #
 ###############################################################################
 
-##################################
+###############################################################################
 Open Source Release <next-release>
-##################################
+###############################################################################
+
+###############################################################################
+Open Source Release 27.0 (Cobalt)
+###############################################################################
 
+-!  Kernel    [2023-05-15] New machdep mechanism, based on YAML files. A new
+              make_machdep.py script allows automatic machdep creation from a
+              C11-compatible (cross-)compiler.
+-   Eva       [2023-05-04] The octagon domain can now infer relations between
+              any lvalues of integer or pointer types.
+-*  Ivette    [2023-05-02] Ends properly frama-c process when Ivette is closed.
+-*  Ivette    [2023-05-02] Custom views are correctly saved and reloaded.
+-*  Eva       [2023-05-02] Fixes interpretation of Eva annotations at the end of
+              a block, and of multiple split annotations after a function call.
+-   Eva       [2023-04-24] When possible, Eva shows the name of enumeration tags
+              instead of their integer values, in the log and the GUI.
+-   Aorai     [2023-04-24] Allows comments in .ya automata files.
+-   Aorai     [2023-04-24] Supports specification about floating-point variables.
+-   Ivette    [2023-04-24] New callgraph component.
+-   Ivette    [2023-04-07] The values table shows the status of uninitialized
+              and escaping variables.
+-   Eva       [2023-04-05] Better display of large integer sets for high values
+              of the -eva-ilevel parameter.
+-   Ivette    [2023-03-31] The values table shows values of function parameters.
+-   Ivette    [2023-03-31] The values table can show the logical status of ACSL
+              predicates, and the values of C lvalues in these predicates.
+o!  GUI       [2023-03-27] Remove GTK2 bindings. Only support GTK3 as of now.
+-   Ivette    [2023-03-23] Improves function filtering in the left sidebar.
+-   Ivette    [2023-03-23] Better display of dead and non-terminating statements.
+-*  Eva       [2023-03-13] Fixes a soundness bug of the equality domain when
+              the same equality holds in two programs paths, but involving a
+              pointer pointing to different variables in the two paths.
 -   Kernel    [2023-03-03] Deprecate option -c11 (now enabled by default).
+-   Ivette    [2023-02-15] Shows information about C types in the Inspector.
+-   Eva       [2023-02-06] Fixes performance issues on programs with too many
+              function calls (more than 20000 callsites).
 -!  Kernel    [2023-01-25] Add support for C11's _Generic. Modifies Cabs AST.
+-*  Eva       [2023-01-16] Fixes unsoundness of the bitwise domain on shifts
+              and casts on big-endian architectures.
+-   Eva       [2023-01-12] Better partitioning splits on ACSL predicates.
 
-###############################
+###############################################################################
 Open Source Release 26.1 (Iron)
-###############################
+###############################################################################
 
 -   Logic     [2023-01-16] Accept \ghost attribute in logic annotations (##2638)
 -   Logic     [2023-01-10] Fix issue in pretty-printing ranges (##2639)
 
-###############################
+###############################################################################
 Open Source Release 26.0 (Iron)
-###############################
+###############################################################################
 
 -   Ivette    [2022-10-26] After an Eva analysis with taint, the taint status of
               lvalues is shown in the Inspector component and in Dive graphs.
@@ -68,9 +105,9 @@ o!  Pdg       [2022-07-01] Removed from Db. Use proper Pdg API instead.
 -   Eva       [2022-05-11] Avoid false alarms of partially overlapping lvalue
               assignments when writing a struct array from itself.
 
-####################################
+###############################################################################
 Open Source Release 25.0 (Manganese)
-####################################
+###############################################################################
 
 o   Kernel    [2022-05-03] Prototype of AST comparison between two versions
               of the same program, via the new option -ast-diff.
@@ -108,9 +145,9 @@ o!  Kernel    [2021-11-29] Integer.pretty does not have the optional argument
               hexa anymore. Use Integer.pretty_hex or Integer.pp_hex if you
               want to print integers in hexadecimal format.
 
-###################################
+###############################################################################
 Open Source Release 24.0 (Chromium)
-###################################
+###############################################################################
 
 -*  Eva       [2022-01-19] Always emits alarms about initialization, escaping
               pointers and special floating-point values for the arguments of
@@ -173,13 +210,13 @@ o   Ptests    [2021-06-03] Add new PLUGIN directive and new predefined macros.
               Tainted properties can then be seen in the future GUI Ivette.
 -   Eva       [2021-05-11] Support for ACSL predicate \is_infinite.
 
-###################################
+###############################################################################
 Open Source Release 23.1 (Vanadium)
-###################################
+###############################################################################
 
-###################################
+###############################################################################
 Open Source Release 23.0 (Vanadium)
-###################################
+###############################################################################
 
 -*  Kernel    [2021-04-26] Do not crash on _Alignof(void): accept or properly
               reject, depending on machdep. Fixes pub/frama-c#2551
@@ -253,9 +290,9 @@ o   Kernel    [2020-11-27] Extract builtin-related functions from module Cil
               Frama_C_dump_each in ghost code.
 -   Metrics   [2020-10-27] Add json output in addition to text and html.
 
-###################################
+###############################################################################
 Open Source Release 22.0 (Titanium)
-###################################
+###############################################################################
 
 -   MdR       [2020-10-19] Update Sarif output to 2.1.0 + prettier URI
 -   Dev       [2020-10-20] Support for OCamlGraph 2.0.0
@@ -302,13 +339,13 @@ Open Source Release 22.0 (Titanium)
 -   Eva       [2020-05-20] Supports the ACSL mathematical operator \abs
 -   Kernel    [2020-05-18] Support for C11's _Noreturn function specifier
 
-###################################
+###############################################################################
 Open Source Release 21.1 (Scandium)
-###################################
+###############################################################################
 
-###################################
+###############################################################################
 Open Source Release 21.0 (Scandium)
-###################################
+###############################################################################
 
 -*  Doc       [2020-05-07] Fixes internal refs in generated pdfs (fixes #2505)
 -*  Kernel    [2020-05-04] Accept UCN-encoded unicode char in ACSL (fixes #@849)
@@ -388,9 +425,9 @@ o!  Kernel    [2020-02-04] Removed FCBuffer, FCMap and FCSet. Use directly
                 overrides the global option for the given functions;
               - via /*@ subdivide N; */ annotations on specific statements.
 
-##################################
+###############################################################################
 Open Source Release 20.0 (Calcium)
-##################################
+###############################################################################
 
 -   Eva       [2019-11-25] In the summary, fixes the number of alarms by
               category when the RTE plugin is used, and do not count logical
@@ -447,9 +484,9 @@ o!  Kernel    [2019-06-28] removes AST constructors TCoerce, TCoerceE,
               PLCoercion, PLCoercionE, Psubtype and PLsubtype
 -*  Kernel    [2019-06-20] fixes dangling ref when removing unused static local
 
-####################################
+###############################################################################
 Open Source Release 19.0 (Potassium)
-####################################
+###############################################################################
 
 -*  RTE       [2019-05-24] fixes a crash when visiting variable declarations
 -   Eva       [2019-04-19] The new annotation /*@ split exp; */ enumerates the
@@ -516,9 +553,9 @@ o   Kernel    [2018-12-11] New functions for retrieving major and minor version
 -*  Kernel    [2018-12-04] Fixes AST integrity check wrt volatile accesses
 -*  Kernel    [2018-11-21] Fixes #@553 - pretty-printing of basic asm template
 
-################################
+###############################################################################
 Open Source Release 18.0 (Argon)
-################################
+###############################################################################
 
 -!  Kernel    [2018-10-24] Log.error and Log.failure will eventually make
               Frama-C exit with a non-zero status. Fixes #@552
@@ -627,15 +664,15 @@ o*  Ptests    [2018-07-02] Do not keep oracles for empty stderr. Fixes #@402
               specific code annotations /*@ loop unroll N; */. The new strategy
               may affect analyses even without loop unrolling.
 
-############################################
+###############################################################################
 Open Source Release 17.1 (Chlorine-20180502)
-############################################
+###############################################################################
 
 -  Libc       [2018-07-05] Fix C++ compatibility for Frama-Clang plug-in
 
-############################################
+###############################################################################
 Open Source Release 17.0 (Chlorine-20180501)
-############################################
+###############################################################################
 
 -  Eva        [2018-04-25] Added scripts and templates to help automate case
               studies (in $FRAMAC_SHARE/analysis-scripts)
@@ -767,9 +804,9 @@ o! Eva        [2017-11-09] The Fval module now supports NaN and infinite values.
 -* Eva        [2017-10-27] Fix bug in the handling of non-explicitly volatile
               fields inside volatile structs or unions
 
-##########################################
+###############################################################################
 Open Source Release 16.0 (Sulfur-20171101)
-##########################################
+###############################################################################
 
 -* Eva        [2017-10-27] Fix bugs when evaluating \ìnitialized, \dangling
               and \separated on addresses of bitfields
@@ -900,9 +937,9 @@ o! Kernel     [2017-04-27] Completely separate types between Cil_types and
 -  Eva        [2017-04-06] More precise evaluation of \initialized and
               \dangling predicates.
 
-##############################################
+###############################################################################
 Open Source Release 15.0 (Phosphorus-20170501)
-##############################################
+###############################################################################
 
 -* Eva        [2017-05-08] Fix widening in the gauges domain, in particular with
               nested loops and pointers that change base address through
@@ -987,9 +1024,9 @@ o! Gui        [2017-03-10] Signature change for constructor
 o* Eva        [2016-10-22] Functions Db.Value.fun_set_args and
               Db.Value.globals_set_initial_state are now compatible with Eva.
 
-###########################################
+###############################################################################
 Open Source Release 14.0 (Silicon-20161101)
-###########################################
+###############################################################################
 
 -*! Eva       [2016-10-29] Fix soundness bug on statements with RTE or
               programmatically-added user assertions (bts #2258). This
@@ -1136,9 +1173,9 @@ o  Makefile   [2016-03-31] Warnings and warn-error are activated only if a file
 o! Kernel     [2016-03-29] Functions Integer.pgcd and Integer.ppcm are now
               guaranteed to return a positive result.
 
-#############################################
+###############################################################################
 Open Source Release 13.0 (Aluminium-20160502)
-#############################################
+###############################################################################
 
 -  Value      [2016-04-19] Support for evaluation of predicate
               \valid_read_string on constant strings.
@@ -1311,9 +1348,9 @@ o  Ptests     [2015-07-29] New EXEC: directive.
 -  Kernel     [2015-07-01] New option -remove-projects.
 -  Kernel     [2015-06-30] New option -set-project-as-default.
 
-#############################################
+###############################################################################
 Open Source Release 12.0 (Magnesium-20151002)
-#############################################
+###############################################################################
 
 o! Kernel     [2016-01-03] Modules Dataflow is deprecated, and will be removed
               in Aluminium. Module Dataflow2 offers a very similar but simpler
@@ -1535,9 +1572,9 @@ o! Kernel     [2015-30-01] Fixed bug #!2012 about combining
               subdividing may avoid the emission of an alarm.
 -  Value      [2015-01-21] Support for \subset predicate.
 
-##########################################
+###############################################################################
 Open Source Release 11.0 (Sodium-20150201)
-##########################################
+###############################################################################
 
 -  Kernel     [2015-02-01] Tests are added to the distrib (make tests).
 -* Logic      [2015-02-09] The ACSL parser accepts qualifiers in logic C types.
@@ -1755,9 +1792,9 @@ o  Logic      [2014-03-04] Annotations.{iter,fold}_all_code_annot are now
 -* Configure   [2014-03-10] fix for autoconf < 2.67 when checking ability
                of default pre-processor to keep comments
 
-########################################
+###############################################################################
 Open Source Release 10.0 (Neon-20140301)
-########################################
+###############################################################################
 
 -* Value      [2014-03-04] Fix bug when writing imprecisely in a struct
               containing a 1-bit wide bitfield (bug #!1671)
@@ -2126,15 +2163,15 @@ o! Value      [2013-05-03] Remove functions Cvalue.Model.pretty_without_null and
               reference to the real function. Removed last argument of
               Cvalue.Model.pretty_filter.
 
-###########################################
+###############################################################################
 Open Source Release 9.2 (Fluorine-20130601)
-###########################################
+###############################################################################
 
 -* Value      [2013-06-11] Add missing C library files.
 
-###########################################
+###############################################################################
 Open Source Release 9.1 (Fluorine-20130501)
-###########################################
+###############################################################################
 
 -  Value      [2013-05-22] Better precision for ^ (bitwise xor) operator
               when applied on intervals of positive integers
@@ -2147,9 +2184,9 @@ o* Kernel     [2013-05-06] Fixed Type.pp_ml_name for polymorphic types
 -* Makefile   [2013-05-06] Fixed installation directory of the doc in
               plug-in's Makefile (bug #1278).
 
-###########################################
+###############################################################################
 Open Source Release 9.0 (Fluorine-20130401)
-###########################################
+###############################################################################
 
 o! Cil        [2013-04-11] Remove Cil pretty-printer. Use module Printer
               instead. The script bin/oxygen2fluorine.sh may be used to
@@ -2405,9 +2442,9 @@ o  Kernel     [2012-09-20] Provide Datatype.triple and Datatype.quadruple
 o* Kernel     [2012-09-20] Fixed consistency check of descriptor when
               building polymorphic datatypes (fixed bts #1277).
 
-#########################################
+###############################################################################
 Open Source Release 8.0 (Oxygen-20120901)
-#########################################
+###############################################################################
 
 -! Kernel     [2012-09-17] Remove useless negative options -no-help,
               -no-version, -no-print-share-path, -no-print-lib-path and
@@ -2786,9 +2823,9 @@ o! Kernel     [2011-10-18] Logic_preprocess.file takes an additional parameter,
               completely invalid. Soundness was not affected (the
               alarm for whatever made e invalid was present).
 
-###########################################
+###############################################################################
 Open Source Release 7.0 (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.
@@ -3240,9 +3277,9 @@ o  Cil/Logic  [2011-02-16] New functions Clexer.is_c_keyword and
 -* Value      [2011-02-09] Changes related to 0., +0., -0., sort of thing.
               Unwarranted loss of precision fixed.
 
-#########################################
+###############################################################################
 Open Source Release 6.2 (Carbon-20110201)
-#########################################
+###############################################################################
 
 -  WP         [2011-02-07] Plug-in WP removed from kernel-releases (now an
               independent plug-in).
@@ -3353,17 +3390,17 @@ o* Cil        [2010-12-20] Fixed bug #645. Ast_info.constant_expr,
               ~loc:Cil_datatype.Location.unknown which is most of the time
               not accurate.
 
-#########################################
+###############################################################################
 Open Source Release 6.1 (Carbon-20101202)
-#########################################
+###############################################################################
 
 -* WP         [2010-12-16] Fixed bug #639: no more Coq compilation to shared
               directory.
 - WP          [2010-12-16] Accessibility of all provers from gui.
 
-#########################################
+###############################################################################
 Open Source Release 6.0 (Carbon-20101201)
-#########################################
+###############################################################################
 
 -! Kernel     [2010-12-13] Fixed bug #548: limit.h now syntactically correct.
               Architectures other than x86_32 still unsupported.
@@ -3564,9 +3601,9 @@ o! Kernel     [2010-04-22] Ptmap (resp. Ptset) is renamed into Hptmap (Hptset)
 +  Logic      [2010-04-13] #!346 Formals have an \old label when used in post
               conditions
 
-########################################
+###############################################################################
 Open Source Release 5.0 (Boron-20100401)
-########################################
+###############################################################################
 
 -  Kernel     [2010-04-12] Preliminary standard C library in $FRAMAC_SHARE/libc
 o* Cil        [2010-04-12] New hook after Cabs elaboration (fix bug #!446)
@@ -3735,9 +3772,9 @@ o! Cil        [2009-09-28] pAssigns now prints directly a whole list of assigns
 -  Value      [2009-09-25] Improved treatment of "assigns p[..]" clauses
               in -input
 
-############################################
+###############################################################################
 Open Source Release 4.2 (Beryllium-20090902)
-############################################
+###############################################################################
 
 -* Obfuscator [2009-09-23] obfuscator does not lose links between logic
               and C variables anymore (bts #250).
@@ -3787,9 +3824,9 @@ o* Makefile   [2009-09-18] Fixed bugs with the use of PLUGIN_EXTRA_BYTE
               which does not support native dynlink and with ocaml >= 3.11
               (bts #224).
 
-############################################
+###############################################################################
 Open Source Release 4.1 (Beryllium-20090901)
-############################################
+###############################################################################
 
 -! Syntactic_callgraph [2009-08-27] New design of the callgraph in the GUI.
               Frama-C now requires ocamlgraph 1.2.
@@ -3832,9 +3869,9 @@ o! Cil        [2009-06-24] Added 2 components to Cil_types.typ to optimize
 -* Kernel     [2009-06-24] Restore compatibility with ocaml 3.10.2
 -* Configure  [2009-06-24] Fixed bug with --disable-gui in configure.in
 
-############################################
+###############################################################################
 Open Source Release 4.0 (Beryllium-20090601)
-############################################
+###############################################################################
 
 o  Value      [2009-06-23] New constructor Signed_overflow_alarm for type
               Alarms.t
@@ -4024,9 +4061,9 @@ o! Kernel     [2009-01-05] Some changes in API of module Type
 -  Value      [2008-12-18] Improved support for state reduction on a
               memory read.
 
-##########################################
+###############################################################################
 Open Source Release 3.1 (Lithium-20081201)
-##########################################
+###############################################################################
 
 -! GUI        [2008-12-09] Improved consistency of some information messages.
 -  Value      [2008-12-09] Abstract structs are now supported in
@@ -4071,9 +4108,9 @@ o  Cil        [2008-11-17] New methods for visiting compinfo, enuminfo,
 o  Makefile   [2008-11-03] Support for native compilation in Makefile.template
               (require ocaml >= 3.11).
 
-##########################################
+###############################################################################
 Open Source Release 3.0 (Lithium-20081002)
-##########################################
+###############################################################################
 
 -! Value      [2008-10-23] Changed behavior of option
               -context-valid-pointers to make it more like the
@@ -4133,9 +4170,9 @@ o! Kernel     [2008-09-11] Refined UnspecifiedSequence information.
 o! Cil        [2008-07-17] AST changes for unspecified sequences (experimental).
 -* Jessie     [2008-07-16] Fixed path problems with binary distributions.
 
-#########################################
+###############################################################################
 Open Source Release 2.0 (Helium-20080701)
-#########################################
+###############################################################################
 
 -  Occurrence [2008-07-11] Occurrences of a variable can be computed from
               any occurrence of the program (not only from its declaration).
@@ -4204,17 +4241,17 @@ o! Logic      [2008-06-24] AST changes for invariants.
 -* Kernel     [2008-06-03] Correct promotion rules from bitfields to integers.
 -* Kernel     [2008-06-02] -machdep was ignored (bts #?309).
 
-###########################################
+###############################################################################
 Open Source Release 1.2 (Hydrogen-20080502)
-###########################################
+###############################################################################
 
 o* Makefile   [2008-05-21] Fixed bug in "make clean-doc" (and "make distclean").
 -  GUI        [2008-05-19] All internal options are available in the GUI
               preferences pannel.
 
-###########################################
+###############################################################################
 Open Source Release 1.1 (Hydrogen-20080501)
-###########################################
+###############################################################################
 
 -! Value      [2008-04-24] Display a warning whenever an uninitialized value
               causes the death of a branch.
@@ -4240,9 +4277,9 @@ o  GUI        [2008-04-07] Project management redesigned for older Gtk and
 -* Kernel     [2008-04-01] Various Win32 path fixes.
 -  Kernel     [2008-04-01] Option -no-unicode : do not print Unicode chars.
 
-######################################
+###############################################################################
 Binary Release 1.0 (Hydrogen-20080302)
-######################################
+###############################################################################
 
 -  Occurrence [2008-03-17] New option -occurrence.
 -  Occurrence [2008-03-17] First release of the plug-in.
@@ -4252,9 +4289,9 @@ Binary Release 1.0 (Hydrogen-20080302)
 -* Project    [2008-03-14] Fixed bug with checksum computation during save/load.
 -* Slicing    [2008-02-25] Fixed bug in interprocedural slicing (bts #?201).
 
-###########################################
+###############################################################################
 Open Source Release 1.0 (Hydrogen-20080301)
-###########################################
+###############################################################################
 
 -  Kernel     [2008-03-01] First release.
 
diff --git a/Makefile b/Makefile
index 9d94325ae423e998f608e5d2d06ac95347178f4e..e3ca12690f9ecc3cfe1c64a31c35aa2e783aa515 100644
--- a/Makefile
+++ b/Makefile
@@ -73,6 +73,21 @@ endif
 	dune clean
 	rm -rf _build .merlin
 
+##############################################################################
+# IVETTE
+################################
+
+.PHONY: ivette ivette-dev
+
+ivette: all
+	@$(MAKE) -C ivette
+
+ivette-api: all
+	@$(MAKE) -C ivette api
+
+ivette-dev: all
+	@$(MAKE) -C ivette dev
+
 ##############################################################################
 # HELP
 ################################
diff --git a/README.md b/README.md
index c79e89f7f68b7e95c4358f2c08ef2435f371c608..667cd21699597ecd39423c8b728879a6627c681f 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,6 @@ called **plug-ins**. Plug-ins can build upon results computed by other
 plug-ins in the platform.
 
 Thanks to this approach, Frama-C provides sophisticated tools, including:
-
 - an analyzer based on abstract interpretation, aimed at verifying
   the absence of run-time errors (**Eva**);
 - a program proof framework based on weakest precondition calculus (**WP**);
diff --git a/VERSION b/VERSION
index 8d4b0111158d4ed44ddccdd1457f13b0e01a41f2..c49dfde59ea4943a4fad4f6f08b7c34f0d01e99d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-26.1+dev
+27.0+dev
diff --git a/VERSION_CODENAME b/VERSION_CODENAME
index c9098b37e740d4c28384b3bee6358d2276ca8797..ae1216c1668e0b1213b1fff0a69d3f1a58409744 100644
--- a/VERSION_CODENAME
+++ b/VERSION_CODENAME
@@ -1 +1 @@
-Iron
+Cobalt
diff --git a/bin/frama-c b/bin/frama-c
index 86398b26384daab1c1da65bfb4f7ba3e7f301a34..88838755bcbd17e06054b3cdd1f6666a0b0fc7c1 100755
--- a/bin/frama-c
+++ b/bin/frama-c
@@ -22,4 +22,4 @@
 ##########################################################################
 
 
-dune exec --root=$(dirname $0)/.. --no-build frama-c -- "$@"
+dune exec --root=$(dirname $0)/.. --no-build --no-print-directory -- frama-c "$@"
diff --git a/bin/test.sh b/bin/test.sh
index 2e9558da3943989b9fb0281c5226ec96da649254..6faa03802ec431d776bdccf21c4d0c300117f360 100755
--- a/bin/test.sh
+++ b/bin/test.sh
@@ -26,12 +26,14 @@ CONFIG="<all>"
 VERBOSE=
 UPDATE=
 LOGS=
+COMMIT=
 TESTS=
 SAVE=
 
 DUNE_ALIAS=
 DUNE_OPT=
 DUNE_LOG=./.test-errors.log
+ALIAS_NAME=ptests
 CACHEDIR=$(pwd -P)/.wp-cache
 FRAMAC_WP_CACHE_GIT=git@git.frama-c.com:frama-c/wp-cache.git
 
@@ -61,11 +63,13 @@ function Usage
     echo ""
     echo "OPTIONS"
     echo ""
+    echo "  -n|--name <alias>   set dune alias name (default to ptests)"
     echo "  -r|--clean          clean (remove all) test results (includes -p)"
     echo "  -p|--ptests         prepare (all) dune files"
     echo "  -w|--wp-cache       prepare (pull) WP-cache"
-    echo "  -u|--update         run tests and update (local) WP-cache"
+    echo "  -u|--wp-update      update (pull+add) WP-cache"
     echo "  -l|--logs           print output of tests (single file, no diff)"
+    echo "  -k|--commit         commit results as oracles (single file, no diff)"
     echo "  -s|--save           save dune logs into $DUNE_LOG"
     echo "  -v|--verbose        print executed commands"
     echo "  -h|--help           print this help"
@@ -206,15 +210,15 @@ function TestDir
     CloneCache
     case "$CONFIG" in
         "<all>")
-            ALIAS=$1/ptests
+            ALIAS=$1/${ALIAS_NAME}
             CFG="(all configs)"
             ;;
         "<default>")
-            ALIAS=$1/ptests_config
+            ALIAS=$1/${ALIAS_NAME}_config
             CFG="(default config)"
             ;;
         *)
-            ALIAS=$1/ptests_config_$CONFIG
+            ALIAS=$1/${ALIAS_NAME}_config_$CONFIG
             CFG="(config $CONFIG)"
             ;;
     esac
@@ -247,6 +251,9 @@ function TestFile
     else
         ALIAS=$DIR/$RESULT/${FILE%.*}.diff
     fi
+    if [ "$COMMIT" = "yes" ]; then
+        COMMITS="${COMMITS} $DIR/$RESULT/${FILE%.*}"
+    fi
     Head "Register test on file $1 $CFG"
     DUNE_ALIAS="${DUNE_ALIAS} @$ALIAS"
 }
@@ -273,6 +280,27 @@ function Register
     done
 }
 
+# --------------------------------------------------------------------------
+# ---  Tests Commits
+# --------------------------------------------------------------------------
+
+function Commits
+{
+    while [ "$1" != "" ]
+    do
+        cd _build/default
+        for log in $1*.res.log
+        do
+            echo "Commit $log"
+            dest="${log//result/oracle}"
+            dest="${dest//res.log/res.oracle}"
+            cp -f $log "../../$dest"
+        done
+        cd ../..
+        shift
+    done
+}
+
 # --------------------------------------------------------------------------
 # ---  Tests Numbering
 # --------------------------------------------------------------------------
@@ -303,8 +331,9 @@ function Status
 
     #-- Check wp-cache status
     if [ "$UPDATE" = "yes" ]; then
-        Head "Check $FRAMAC_WP_CACHEDIR status"
+        Head "Update $FRAMAC_WP_CACHEDIR and check status"
         RequiredTools git
+        Run git -C $FRAMAC_WP_CACHEDIR add -A
         Run git -C $FRAMAC_WP_CACHEDIR status -s
     fi
 }
@@ -334,7 +363,8 @@ do
         "-w"|"--wp-cache")
             PullCache
             ;;
-        "-u"|"--update")
+        "-u"|"--wp-update")
+            PullCache
             FRAMAC_WP_CACHE=update
             UPDATE=yes
             ;;
@@ -345,8 +375,11 @@ do
         "-l"|"--logs")
             LOGS=yes
             ;;
+        "-k"|"--commit")
+            COMMIT=yes
+            ;;
         "-s"|"--save" )
-             SAVE=yes
+            SAVE=yes
             ;;
         "-d"|"--default")
             CONFIG="<default>"
@@ -355,6 +388,10 @@ do
             CONFIG=$2
             shift
             ;;
+        "-n"|"--name")
+            ALIAS_NAME=$2
+            shift
+            ;;
         "-a"|"--all")
             TESTS=""
             for dir in $TEST_DIRS ; do
@@ -371,4 +408,5 @@ do
 done
 Register $TESTS
 RunAlias ${DUNE_ALIAS}
+Commits ${COMMITS}
 Status $DUNE_LOG
diff --git a/dev/dune-workspace.bench b/dev/dune-workspace.bench
index 87e6d04e0ad58aba035cac6a3f7b7c68eda27674..1f5ad5f7195c1c589acd1a37e04a56aa999a51c3 100644
--- a/dev/dune-workspace.bench
+++ b/dev/dune-workspace.bench
@@ -1,4 +1,26 @@
 (lang dune 3.2)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;                                                                        ;;
+;;  This file is part of Frama-C.                                         ;;
+;;                                                                        ;;
+;;  Copyright (C) 2007-2023                                               ;;
+;;    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).            ;;
+;;                                                                        ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
 (context
  (default
   (name bench)
diff --git a/dev/set-version.sh b/dev/set-version.sh
new file mode 100755
index 0000000000000000000000000000000000000000..09f362f28ffe62fe940a815edbf52df74b40abcf
--- /dev/null
+++ b/dev/set-version.sh
@@ -0,0 +1,127 @@
+#! /bin/bash
+##########################################################################
+#                                                                        #
+#  This file is part of Frama-C.                                         #
+#                                                                        #
+#  Copyright (C) 2007-2023                                               #
+#    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).            #
+#                                                                        #
+##########################################################################
+
+NEXT=$1
+
+if ! test -f VERSION; then
+  echo "This script must be run from Frama-C root directory"
+  exit 2
+fi
+if test -z "$NEXT"; then
+  echo "Missing argument. Usage is:"
+  echo "\$ ./dev/set-version.sh [<NN.M>|dev]"
+  echo "See the Release Management Documentation for an example."
+  exit 2
+fi
+
+# For macOS: use gsed if available, otherwise test if sed is BSD
+if command -v gsed &>/dev/null; then
+  SED=gsed
+else
+  if sed --version 2>/dev/null | grep -q GNU; then
+    SED=sed
+  else
+    echo "GNU sed required"
+    exit 1
+  fi
+fi
+
+CURRENT=$(cat VERSION)
+CURRENT_MAJOR=$(echo "$CURRENT" | $SED -e s/\\\([0-9]*\\\).[0-9]*.*/\\1/)
+CURRENT_MINOR=$(echo "$CURRENT" | $SED -e s/[0-9]*.\\\([0-9]*\\\).*/\\1/)
+CURRENT_CODENAME=$(grep "$CURRENT_MAJOR " ./doc/release/periodic-elements.txt | cut -d " " -f2)
+
+if [[ $NEXT == "dev" ]]; then
+  echo "Set VERSION to $CURRENT+dev"
+  echo "Continue? [y/N] "
+  read CHOICE
+  case "${CHOICE}" in
+  "Y" | "y") ;;
+  *) exit 1 ;;
+  esac
+
+  echo "$CURRENT+dev" >VERSION
+  $SED -i "s/^version: .*/version: \"$CURRENT+dev\"/g" opam
+  $SED -i "s/^version: .*/version: \"$CURRENT+dev\"/g" tools/lint/frama-c-lint.opam
+  $SED -i "s/^version: .*/version: \"$CURRENT+dev\"/g" tools/hdrck/frama-c-hdrck.opam
+else
+  NEXT_MAJOR=$(echo "$NEXT" | $SED -e s/\\\([0-9]*\\\).[0-9]*.*/\\1/)
+  NEXT_MINOR=$(echo "$NEXT" | $SED -e s/[0-9]*.\\\([0-9]*\\\).*/\\1/)
+  NEXT_CODENAME=$(grep "$NEXT_MAJOR " ./doc/release/periodic-elements.txt | cut -d " " -f2)
+
+  echo "NEXT VERSION is:"
+  echo "- MAJOR:    $NEXT_MAJOR"
+  echo "- MINOR:    $NEXT_MINOR"
+  echo "- CODENAME: $NEXT_CODENAME"
+
+  echo ""
+  echo "Continue? [y/N] "
+  read CHOICE
+  case "${CHOICE}" in
+  "Y" | "y") ;;
+  *) exit 1 ;;
+  esac
+
+  # Version
+
+  echo "$NEXT" >VERSION
+  echo "$NEXT_CODENAME" >VERSION_CODENAME
+
+  # Opam files
+  $SED -i "s/^version: .*/version: \"$NEXT_MAJOR.$NEXT_MINOR\"/g" opam
+  $SED -i "s/\(.*\)$CURRENT_MAJOR.$CURRENT_MINOR-$CURRENT_CODENAME\(.*\)/\1$NEXT_MAJOR.$NEXT_MINOR-$NEXT_CODENAME\2/g" opam
+
+  $SED -i "s/^version: .*/version: \"$NEXT_MAJOR.$NEXT_MINOR\"/g" tools/lint/frama-c-lint.opam
+  $SED -i "s/^version: .*/version: \"$NEXT_MAJOR.$NEXT_MINOR\"/g" tools/hdrck/frama-c-hdrck.opam
+
+  # Changelogs
+
+  FC_CL_MSG_FUTURE="Open Source Release <next-release>"
+  FC_CL_MSG_NEXT="Open Source Release $NEXT_MAJOR.$NEXT_MINOR ($NEXT_CODENAME)"
+  FC_CL_LIN="###############################################################################"
+
+  $SED -i "s/\($FC_CL_MSG_FUTURE\)/\1\n$FC_CL_LIN\n\n$FC_CL_LIN\n$FC_CL_MSG_NEXT/g" Changelog
+
+  EA_CL_MSG_FUTURE="Plugin E-ACSL <next-release>"
+  EA_CL_MSG_NEXT="Plugin E-ACSL $NEXT_MAJOR.$NEXT_MINOR ($NEXT_CODENAME)"
+
+  $SED -i "s/\($EA_CL_MSG_FUTURE\)/\1\n$FC_CL_LIN\n\n$FC_CL_LIN\n$EA_CL_MSG_NEXT/g" src/plugins/e-acsl/doc/Changelog
+
+  WP_CL_MSG_FUTURE="Plugin WP <next-release>"
+  WP_CL_MSG_NEXT="Plugin WP $NEXT_MAJOR.$NEXT_MINOR ($NEXT_CODENAME)"
+
+  $SED -i "s/\($WP_CL_MSG_FUTURE\)/\1\n$FC_CL_LIN\n\n$FC_CL_LIN\n$WP_CL_MSG_NEXT/g" src/plugins/wp/Changelog
+
+  # API doc
+  find src -name '*.ml*' -exec $SED -i -e "s/Frama-C+dev/${NEXT}-${NEXT_CODENAME}/gI" '{}' ';'
+
+  # Manuals changes
+  $SED -i "s/\(^\\\\section\*{Frama-C+dev}\)/%\1\n\n\\\\section\*{$NEXT_MAJOR.$NEXT_MINOR ($NEXT_CODENAME)}/g" \
+    doc/userman/user-changes.tex
+  $SED -i "s/\(^\\\\section\*{Frama-C+dev}\)/%\1\n\n\\\\section\*{$NEXT_MAJOR.$NEXT_MINOR ($NEXT_CODENAME)}/g" \
+    doc/developer/changes.tex
+  $SED -i "s/\(^\\\\subsection{Frama-C+dev}\)/%\1\n\n\\\\subsection{Frama-C $NEXT_CODENAME}/g" \
+    doc/aorai/main.tex
+  $SED -i "s/\(^\\\\section\*{E-ACSL \\\\eacslpluginversion \\\\eacslplugincodename}\)/%\1\n\n\\\\section\*{E-ACSL $NEXT_MAJOR.$NEXT_MINOR $NEXT_CODENAME}/g" \
+    src/plugins/e-acsl/doc/userman/changes.tex
+fi
diff --git a/doc/aorai/main.tex b/doc/aorai/main.tex
index 0c902318f7b36da17d9035a490b09dcf39f456d2..43ed2deea1de8f2e5f065c624d95c04b8d88d1fe 100644
--- a/doc/aorai/main.tex
+++ b/doc/aorai/main.tex
@@ -1123,6 +1123,8 @@ The plug-in is composed of three parts:
 
 
 \section{Recent updates}
+%\subsection{Frama-C+dev}
+
 \subsection{Frama-C Iron}
 \begin{itemize}
 \item Remove obsolete support for LTL and Promela input language
diff --git a/doc/developer/advance.tex b/doc/developer/advance.tex
index bdfec9acc732ea0b1516a19ee06f899857d7360f..13357f76e11e74b919a909d9d7c617ccaf669c6e 100644
--- a/doc/developer/advance.tex
+++ b/doc/developer/advance.tex
@@ -3213,114 +3213,60 @@ type-checked. Transformation hooks are registered through
   None.
 \end{prereq}
 
+\subsection{Generating a custom model}\label{sec:gener-cust-model}
 Several aspects of the C standard that are implementation-defined, such as
 the width of standard integer types, endianness, signedness of the
 \texttt{char} type, etc., as well as a few compiler and architecture specific
 features, can be customized using a \texttt{machdep} configuration,
 defining a new machine model.
 
-To create a new machine model, define an instance of \verb+Cil_types.mach+%
-\scodeidxdef{Cil\_types}{mach}. You can base it on the examples available in
-\verb+tests/misc/custom_machdep/custom_machdep.ml+ and
-\verb+src/kernel_internals/runtime/machdeps.ml+.
-The new definition can be added to \framac's database using
-\verb+File.new_machdep+\scodeidxdef{File}{new\_machdep}.
-
-\begin{example}
-  A custom machine description may be implemented as follows
-  (the meaning of each field is presented later in this section):
-\begin{ocamlcode}
-let my_machine =
-{
-  version          = "generic C compiler for my machine";
-  compiler         = "generic";
-  cpp_arch_flags   = [];
-  sizeof_short     = 2;
-  sizeof_int       = 4;
-  sizeof_long      = 4;
-  sizeof_longlong  = 8;
-  sizeof_ptr       = 4;
-  sizeof_float     = 4;
-  sizeof_double    = 8;
-  sizeof_longdouble  = 12;
-  sizeof_void      = 1;
-  sizeof_fun       = 1;
-  size_t = "unsigned long";
-  wchar_t = "int";
-  ptrdiff_t = "int";
-  alignof_short = 2;
-  alignof_int = 4;
-  alignof_long = 4;
-  alignof_longlong = 4;
-  alignof_ptr = 4;
-  alignof_float = 4;
-  alignof_double = 4;
-  alignof_longdouble = 4;
-  alignof_str = 1;
-  alignof_fun = 1;
-  alignof_aligned = 16;
-  char_is_unsigned = false;
-  const_string_literals = true;
-  little_endian = true;
-  underscore_name = false ;
-  has__builtin_va_list = true;
-}
-
-let () = File.new_machdep "my_machine" my_machine
-\end{ocamlcode}
-\end{example}
-
-\index{Command Line!-machdep@\texttt{-machdep}}%
-After this code is loaded, \framac can be instructed to use the new machine
-model using the \texttt{-machdep} command line option.
-
-If you intend to use \framac's standard library headers, you must also do the
-following:
-
-\begin{itemize}
-\item define constant \verb+__FC_MACHDEP_<CUSTOM>+, replacing \verb+<CUSTOM>+
-  with the name (in uppercase letters) of your created machdep;
-  this can be done via \verb+-cpp-extra-args="-D__FC_MACHDEP_<CUSTOM>"+;
-\item provide a header file with macro definitions corresponding to your \caml
-  definitions. For the most part, these are macros prefixed by \verb+__FC_+,
-  corresponding to standard C macro definitions, {\it e.g.},
-  \verb+__FC_UCHAR_MAX+. These definitions are used by \framac's
-  \verb+<limits.h>+ and other headers to provide the standard C definitions.
-  The test file \verb+tests/misc/custom_machdep/__fc_machdep_custom.h+
-  (reproduced below)
-  contains a complete example of the required definitions. Other examples can
-  be found in \verb+share/libc/__fc_machdep.h+.
-\end{itemize}
-Make sure that your custom header defines the \verb+__FC_MACHDEP+
-include guard, and that the program you are analyzing includes this header
-before all other headers. One way to ensure this without having to modify any
-source files is to use an option such as \verb+-include+ in GCC.
-
-\begin{example}
-  Contents of \verb+tests/misc/custom_machdep/__fc_machdep_custom.h+, used as
-  example for creating custom machdeps. Notice the unusual size for \verb+int+
-  (3 bytes), selected for testing purposes only, and inconsistent with the
-  chosen values for \verb+INT_MIN+ and \verb+INT_MAX+, which do not fit
-  in 3 bytes.
-\lstinputlisting{../../tests/misc/custom_machdep/__fc_machdep_custom.h}
-\end{example}
+Machine models are described as \texttt{YAML} files, following the
+\texttt{machdeps/machdep-schema.yaml} schema in \texttt{FRAMAC\_SHARE}.
+Predefined machdeps are also located in the \texttt{machdeps} directory
+of \framac's \texttt{SHARE} directory and can be used as reference for
+defining new \texttt{machdep}s by hand. It is also possible to automatically
+generate an \texttt{YAML} file with the \texttt{make\_machdep.py} script in
+the \texttt{machdeps/make\_machdep} directory. This script requires a
+C11-compliant cross-compiler for the architecture you want to describe.
+Its main options are:
+\begin{description}
+\item \texttt{-compiler <c>}: the cross-compiler to be used for generating
+  the machdep.
+\item \texttt{-cpp-arch-flags <flag>}: an option given to the compiler for
+selecting the desired architecture. Multiple occurrences of this option can
+occur if you want to pass several options.
+\item \texttt{-o <file>}: put the generated YAML into the given file (default
+is to use standard output).
+\item \texttt{--help}: outputs the list of all options of the script.
+\end{description}
 
-An example of the complete command-line is presented below, for a custom
-machdep called \texttt{myarch}, defined in file \verb+my_machdep.ml+ and
-with stdlib constants defined in \verb+machdep_myarch.h+:
+Note that for some compiler setups, notably for non-POSIX compilation targets,
+the script may fail to find an appropriate value for some fields and will
+instead put some default value. In that case, warnings will give the names of
+the problematic fields. Since the issue likely stems from the fact that the
+corresponding C feature is not supported on the compilation target in the first
+place, in practice, such feature is not expected to be found in code written for
+such target. However, users are invited to review the generated YAML and
+provide more appropriate values for these fields if needed.
 
-\begin{listing-nonumber}
-  frama-c -load-script my_machdep.ml -machdep myarch \
-    -cpp-extra-args="-D__FC_MACHDEP_MYARCH -include machdep_myarch.h"
-\end{listing-nonumber}
+In order to communicate machine-related information to the preprocessor (notably
+the value of standard macros), \framac generates a specific header,
+\verb+__fc_machdep.h+, that is automatically included by the standard headers from
+\framac's standard C library. Field \verb+custom_defs+ of the YAML file allows
+customizing this header (see next section for more information).
 
-\section{Machdep record fields}\label{sec:machdep-fields}
+\subsection{Machdep record fields}\label{sec:machdep-fields}
 
-Each field in the machdep record is succintly described in the \verb+Cil_types+
-module. We present below a thorough description of each field.
+Each field of the machdep is succintly described in the
+\verb+machdep-schema.yaml+ file.
+We present below a thorough description of each field.
 
+\paragraph{Meta-data}
 \begin{description}
 \item[\texttt{version}]: human-readable textual description of the machdep.
+\item[\texttt{machdep\_name}]: name of the machdep, must only contain alphanumeric
+  characters or underscore (\verb+_+). If it is e.g. \verb+custom_name+, the generated header will
+  define a macro of the form \verb+__FC_MACHDEP_CUSTOM_NAME+.
 \item[\texttt{compiler}]: defines whether special compiler-specific extensions
   will be enabled. It should be one of the strings below:
   \begin{itemize}
@@ -3332,15 +3278,17 @@ module. We present below a thorough description of each field.
     compiler-specific extensions.
   \end{itemize}
   Note that some compiler extensions, such as attributes, are always enabled.
-\item[\texttt{cpp\_arch\_flags}]: list of arguments to be added to the
-  command-line when invoking the C preprocessor. Typically used to ensure that
-  multiarch compilers apply the appropriate predefined macros\footnote{Note that
-    the sizes of standard integer types are already defined in the machdep,
-    so they do not depend on these flags.}.
-  E.g. use \verb+["-m32"]+ for a 32-bit machdep when preprocessing with a
-  64-bit multiarch GCC.
+\item[\texttt{cpp\_arch\_flags}]: list of arguments used by the compiler to
+  select the corresponding architecture, e.g. \verb+["-m32"]+ for a 32-bit
+  machdep. Older versions (up to 26.x - Iron) of \framac did pass these flags to the pre-processor,
+  in order for it to define a set of built-in macros related to said architecture.
+  Current versions do not use this field, and rely on \texttt{\texttt{custom\_defs}}
+  containing the appropriate definitions.
   Note that, in practice, very few programs rely on such predefined macros,
   such as \verb+__x86_64+ and \verb+__i386+.
+\end{description}
+\paragraph{Standard sizes and alignment constraints}
+\begin{description}
   \item[\texttt{sizeof\_short}]: size (in bytes) of the \verb+short+ type.
   \item[\texttt{sizeof\_int}]: size (in bytes) of the \verb+int+ type.
   \item[\texttt{sizeof\_long}]: size (in bytes) of the \verb+long+ type.
@@ -3352,7 +3300,7 @@ module. We present below a thorough description of each field.
   \item[\texttt{sizeof\_ptr}]: size (in bytes) of an object (non-function)
     pointer.
   \item[\texttt{sizeof\_float}]: size (in bytes) of a single-precision floating
-    point. In implementations compliant with ISO/IEC/IEEE 60559 -IEEE 754,
+    point. In implementations compliant with ISO/IEC/IEEE 60559 - IEEE 754,
     this is always 4.
   \item[\texttt{sizeof\_double}]: size (in bytes) of a double-precision floating
     point. In implementations compliant with ISO/IEC/IEEE 60559 - IEEE 754,
@@ -3363,16 +3311,10 @@ module. We present below a thorough description of each field.
     \framac plugins,  but this field exists for future expansion, and
     to compute \verb+sizeof+ of aggregates properly.
   \item[\texttt{sizeof\_void}]: the result of evaluating \verb+sizeof(void)+
-    by the compiler (or 0 if unsupported).
+    by the compiler (or negative if unsupported).
   \item[\texttt{sizeof\_fun}]: the result of evaluating \verb+sizeof(f)+, where
     \verb+f+ is a function ({\em not} a function pointer) by the compiler
     (or negative if unsupported).
-  \item[\texttt{size\_t}]: a string containing the actual type that
-    \verb+size_t+ expands to, e.g. \verb+"unsigned long"+.
-  \item[\texttt{wchar\_t}]: a string containing the actual type that
-    \verb+wchar_t+ expands to. If unsupported, you can use \verb+int+.
-  \item[\texttt{ptrdiff\_t}]: a string containing the actual type that
-    \verb+ptrdiff_t+ expands to. If unsupported, you can use \verb+int+.
   \item[\texttt{alignof\_short}]: the result of evaluating
     \verb+_Alignof(short)+.
   \item[\texttt{alignof\_int}]: the result of evaluating \verb+_Alignof(int)+.
@@ -3395,31 +3337,120 @@ module. We present below a thorough description of each field.
     \verb+aligned+ attribute (or 1 if unsupported). This corresponds to the
     default alignment when using \verb+#pragma packed()+ without a numeric
     argument.
+\end{description}
+
+\paragraph{Standard types}
+
+\begin{description}
+\item[\texttt{int\_fast8\_t}]: a string containing the actual type that
+  \verb+int_fast8_t+ expands to. Usually \verb+signed char+.
+\item[\texttt{int\_fast16\_t}]: a string containing the actual type that
+  \verb+int_fast16_t+ expands to. Usually \verb+int+ or \verb+long+.
+\item[\texttt{int\_fast32\_t}]: a string containing the actual type that
+  \verb+int_fast_32_t+ expands to. Usually \verb+int+ or \verb+long+.
+\item[\texttt{int\_fast64\_t}]: a string containing the actual type that
+  \verb+int_fast64_t+ expands to. Usually \verb+long+ or \verb+long long+.
+\item[\texttt{uint\_fast8\_t}]: a string containing the actual type that
+  \verb+uint_fast8_t+ expands to. Usually \verb+unsigned char+.
+\item[\texttt{uint\_fast16\_t}]: a string containing the actual type that
+  \verb+uint_fast16_t+ expands to. Usually \verb+unsigned int+ or \verb+unsigned long+.
+\item[\texttt{uint\_fast32\_t}]: a string containing the actual type that
+  \verb+uint_fast_32_t+ expands to. Usually \verb+unsigned int+ or \verb+unsigned long+.
+\item[\texttt{uint\_fast64\_t}]: a string containing the actual type that
+  \verb+uint_fast64_t+ expands to. Usually \verb+unsigned long+ or
+  \verb+unsigned long long+.
+\item[\texttt{intptr\_t}]: a string containing the actual type that
+  \verb+intptr_t+ expands to, e.g. \verb+long+
+\item[\texttt{uintptr\_t}]: a string containing the actual type that
+  \verb+uintptr_t+ expands to, e.g. \verb+unsigned long+
+\item[\texttt{size\_t}]: a string containing the actual type that
+  \verb+size_t+ expands to, e.g. \verb+unsigned long+.
+\item[\texttt{ssize\_t}]: a string containing the actual type that
+  \verb+ssize_t+ expands to, e.g. \verb+long+
+\item[\texttt{wchar\_t}]: a string containing the actual type that
+  \verb+wchar_t+ expands to. If unsupported, you can use \verb+int+.
+\item[\texttt{ptrdiff\_t}]: a string containing the actual type that
+  \verb+ptrdiff_t+ expands to. If unsupported, you can use \verb+int+.
+\item[\texttt{sig\_atomic\_t}]: a string containing the actual type that
+  \verb+sig_atomic_t+ expands to (i.e. an integer type that can be
+  accessed atomically even in presence of interrupts).
+\item[\texttt{time\_t}]: a string containing the actual type that
+  \verb+time_t+ expands to (i.e. an integer type that can hold time
+  values in seconds).
+\item[\texttt{wint\_t}]: a string containing the actual type that
+  \verb+wint_t+ expands to (i.e. an integer type capable of holding any
+  \verb+wchar_t+ and \verb+WEOF+)
+\end{description}
+
+\paragraph{Standard macros}
+
+Note that all fields described in this paragraph have \texttt{string} values,
+even if they denote numeric constants. In order to avoid errors when loading the
+YAML file, you can force them to be considered as strings by enclosing them between
+single or double quotes, as in \verb+eof: '(-1)'+ (as a sidenote, negative values
+should be enclosed in parentheses, in order to ensure safe macro expansions).
+
+\begin{description}
+  \item[\texttt{bufsiz}]: value of the \texttt{BUFSIZ} macro, i.e. the size
+    of buffers used by I/O functions in \texttt{stdio.h}.
+  \item[\texttt{eof}]: value of the \texttt{EOF} macro, the value returned by input
+    functions in \texttt{stdio.h} to indicate the end of the stream.
+  \item[\texttt{errno}]: list of possible errors with their numeric value. In order
+    to be easier to read, the content of this field is in fact written itself as an
+    object whose fields are the name of the errors. For instance, for a machdep defining
+    only the three errors mandated by the C standard, we would have:
+    \begin{verbatim}
+    errno:
+        edom: 1
+        eilseq: 2
+        erange: 3
+    \end{verbatim}
+  \item[\texttt{filename\_max}]: value of the \texttt{FILENAME\_MAX} macro, which
+    denotes the longest name that is guaranteed to be accepted by \texttt{fopen}.
+  \item[\texttt{fopen\_max}]: value of the \texttt{FOPEN\_MAX} macro, which denotes the
+    greatest number of streams that can be simultaneously opened by the program.
+  \item[\texttt{host\_name\_max}]: value of the \texttt{HOST\_NAME\_MAX} macro, which
+    denotes the maximum length of a hostname (without terminating null byte).
+  \item[\texttt{l\_tmpnam}]: value of the \texttt{L\_tmpnam} macro, which denotes
+    the maximum size of a temporary filename as returned by \texttt{tmpnam}.
+  \item[\texttt{mb\_cur\_max}]: value of the \texttt{MB\_CUR\_MAX} macro, which denotes
+    the maximum number of bytes for a character in the current locale (usually
+    \texttt{'1'}).
+  \item[\texttt{nsig}]: number of possible signals (non-standard macro, can be left
+    empty if undefined for the current machdep).
+  \item[\texttt{path\_max}]: value of the \texttt{PATH\_MAX} macro, which denotes
+    the maximum size (including terminating null) that can be stored in a buffer
+    when returning a pathname.
+  \item[\texttt{posix\_version}]: value of the \texttt{\_POSIX\_VERSION} macro.
+    Leave empty on non-POSIX machdeps.
+  \item[\texttt{rand\_max}]: value of the \texttt{RAND\_MAX} macro, which denotes
+    the maximum value returned by \texttt{rand}.
+  \item[\texttt{tmp\_max}]: value of the \texttt{TMP\_MAX} macro, which denotes
+    the minimum number of temporary filenames returned by \texttt{tmpnam} that
+    are guaranteed to be distinct.
+  \item[\texttt{tty\_name\_max}]: value of the \texttt{TTY\_NAME\_MAX} macro, which
+    denotes the maximum length of a terminal device name (including terminating null byte).
+  \item[\texttt{weof}]: value of the \texttt{WEOF} macro, similar to \texttt{EOF},
+    but for wide chars.
+  \item[\texttt{wordsize}]: value of the \texttt{\_\_WORDSIZE} macro, which denotes
+    the length of a word on the current architecture.
+\end{description}
+
+\paragraph{Other features}
+\begin{description}
   \item[\texttt{char\_is\_unsigned}]: whether type \verb+char+ is unsigned.
-  \item[\texttt{const\_string\_literals}]: whether string literals have const
-    chars, or are writable. If \verb+true+, the following code has undefined
-    behavior, otherwise it is defined: \verb+char *s = "no"; s[0] = 'g';+.
-  \item[\texttt{little\_endian}]: whether the machine is little endian.
-  \item[\texttt{underscore\_name}]: whether the compiler generates assembly
-    labels by prepending \verb+_+ to the identifier. That is, will function
-    \verb+foo()+ have the label \verb+foo+, or \verb+_foo+?
+  \item[\texttt{little\_endian}]: whether the machine is little endian or big
+    endian\footnote{More exotic endianness such as mixed-endian are currently unsupported.}.
   \item[\texttt{has\_\_builtin\_va\_list}]: whether \verb+__builtin_va_list+
     is a (built-in) type known by the preprocessor.
   \item[\texttt{\_\_thread\_is\_keyword}]: whether \verb+__thread+ is a
     keyword (otherwise, it can be used as a standard identifier).
+  \item[\texttt{custom\_defs}]: arbitrary text that will be appended
+    verbatim at the
+    end of the generated header file (this is empty in machdeps that are
+    generated by the \texttt{make\_machdep.py} script).
 \end{description}
 
-\paragraph{Writing a new machdep}
-
-Writing a machdep for a new architecture is not trivial, due to the fact
-that some steps are hard to automate. If you have a working compiler for the
-target architecture, you can use it to produce an executable that will print
-the contents of expressions such as \verb+sizeof(long)+, \verb+_Alignof(int)+,
-etc. You can also use the compiler to test for unsupported features.
-In case \verb+printf+ is not available, you can use the exit code of the
-program (return code of \verb+main+). In case you can only preprocess, but not
-compile and run the program, the assembly code may provide some useful data.
-
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 \section{Visitors}\label{adv:visitors}\index{Visitor|bfit}
@@ -3974,7 +4005,7 @@ can be used in ACSL specification.
 
 Namely, specification:
 
-\begin{lstlisting}[language=C,alsolanguage=ACSL]
+\begin{lstlisting}[style=c]
 /*@ ext_type load: foo ; */
 /*@
   axiomatic Pred {
@@ -4209,9 +4240,9 @@ For quick usage of the library:
 \item install the instrumented \framac: \texttt{make install DUNE\_WS=bench}.
 \item enable instrumentation {\em during execution} of \framac, using the
   \texttt{OCAML\_LANDMARKS} environment variable:
-  \begin{lstlisting}
-    OCAML_LANDMARKS=<options> frama-c [files] [options]
-  \end{lstlisting}
+\begin{logs}
+OCAML_LANDMARKS=<options> frama-c [files] [options]
+\end{logs}
   The easiest setup is \texttt{OCAML\_LANDMARKS=auto}, which will instrument
   everything and output timing information to \texttt{stderr} after
   program termination.
@@ -4219,10 +4250,10 @@ For quick usage of the library:
   output the timing information to file \texttt{landmarks.log}.
 \item you can also run the instrumented \framac without installing it, via
   \texttt{dune exec}:
-  \begin{lstlisting}
-    OCAML_LANDMARKS=auto dune exec --workspace dev/dune-workspace.bench \
-      --context bench -- frama-c [files] [options]
-  \end{lstlisting}
+\begin{logs}
+OCAML_LANDMARKS=auto dune exec --workspace dev/dune-workspace.bench \
+  --context bench -- frama-c [files] [options]
+\end{logs}
   The \verb+--workspace dev/dune-workspace.bench+ argument tells Dune to use
   the workspace in which Landmarks is configured.
 
@@ -4238,8 +4269,49 @@ of the file.
 To instrument a single function: add \verb+[@landmark]+ after the \texttt{let},
 e.g.:
 
-\begin{lstlisting}
+\begin{ocamlcode}
   let[@landmark] add_visitor vis =
-\end{lstlisting}
+\end{ocamlcode}
 
 Check \url{https://github.com/LexiFi/landmarks} for its documentation.
+
+\section{Profiling a custom plug-in}
+
+To profile your own plug-in using Landmarks, do the following:
+
+\begin{enumerate}
+\item Add \verb|(instrumentation (backend landmarks))| to your plug-in's
+  \verb|dune| file, inside the \verb|library| stanza, as in the example below:
+\begin{dunecode}
+ (library
+   (name my-plug-in)
+   (public_name frama-c-my-plug-in.core)
+   ...
+   (libraries frama-c.kernel)
+   (instrumentation (backend landmarks)) ; <<< ADD THIS LINE
+ )
+\end{dunecode}
+\item Create a \verb|dune-workspace.bench| file in your plugin's top-level
+  directory:
+  \listingname{dune-workspace.bench}
+  \duneinput{dune-workspace.bench}
+\item Add \verb|--workspace=dune-workspace.bench| to the \verb|dune build|
+  and \verb|dune install| commands that you run, e.g.:
+\begin{logs}
+dune build --workspace=dune-workspace.bench @install
+dune install --workspace=dune-workspace.bench
+\end{logs}
+This will compile and install the plug-in with Landmarks instrumentation
+enabled. Then you just need to set \verb|OCAML_LANDMARKS| as described in the
+previous section, e.g.:
+\begin{logs}
+OCAML_LANDMARKS=auto frama-c [my-plugin-options]
+\end{logs}
+\item For \verb|dune exec|, you need to add the \verb|--workspace| option
+  as well as \verb|--context bench|. Combined with \verb|OCAML_LANDMARKS|,
+  the command-line will resemble the following:
+\begin{logs}
+OCAML_LANDMARKS=auto dune exec --workspace dev/dune-workspace.bench \
+  --context bench -- frama-c [files] [options]
+\end{logs}
+\end{enumerate}
diff --git a/doc/developer/changes.tex b/doc/developer/changes.tex
index 4e949abc3b74503bb9715505ec5d5ce087691834..d0ee85277359173857a81b900decd4ab713eb009 100644
--- a/doc/developer/changes.tex
+++ b/doc/developer/changes.tex
@@ -5,10 +5,13 @@
 This chapter summarizes the major changes in this documentation between each
 \framac release, from newest to oldest.
 
-%\section*{dev}
-%\begin{itemize}
-%\item …
-%\end{itemize}
+%\section*{Frama-C+dev}
+
+\section*{27.0 (Cobalt)}
+\begin{itemize}
+\item \textbf{Customizing the machine model}: Rewrite section according to new
+  machdep management mechanism
+\end{itemize}
 
 \section*{26.0 Iron}
 \begin{itemize}
diff --git a/doc/developer/dune-workspace.bench b/doc/developer/dune-workspace.bench
new file mode 100644
index 0000000000000000000000000000000000000000..87e6d04e0ad58aba035cac6a3f7b7c68eda27674
--- /dev/null
+++ b/doc/developer/dune-workspace.bench
@@ -0,0 +1,9 @@
+(lang dune 3.2)
+(context
+ (default
+  (name bench)
+  (profile bench)
+  (instrument_with landmarks)
+  (env
+    (_ (env-vars ("OCAML_LANDMARKS" "auto")))))
+)
diff --git a/doc/eva/examples/nondet.c b/doc/eva/examples/nondet.c
index 808ba9c653ee9a33e59b006d03dac4c9224c1a6d..b73510ecab61fbce6e8034709be01b4a68484b06 100644
--- a/doc/eva/examples/nondet.c
+++ b/doc/eva/examples/nondet.c
@@ -1,9 +1,11 @@
 #include "__fc_builtin.h"
 
 int A,B,X;
+int arr[20];
 void main(void)
 {
   A = Frama_C_nondet(6, 15);
   B = Frama_C_interval(-3, 10);
   X = A * B;
+  Frama_C_make_unknown(arr, sizeof(arr));
 }
diff --git a/doc/eva/examples/parametrizing/split-array.log b/doc/eva/examples/parametrizing/split-array.log
index 53a9ddd932748d851458163c1c4c9e1f4d461370..5adefbaf6d4c26f05da62738388ced7a7cab5977 100644
--- a/doc/eva/examples/parametrizing/split-array.log
+++ b/doc/eva/examples/parametrizing/split-array.log
@@ -27,7 +27,7 @@
 [eva:summary] ====== ANALYSIS SUMMARY ======
   ----------------------------------------------------------------------------
   1 function analyzed (out of 1): 100% coverage.
-  In this function, 9 statements reached (out of 9): 100% coverage.
+  In this function, 10 statements reached (out of 10): 100% coverage.
   ----------------------------------------------------------------------------
   No errors or warnings raised during the analysis.
   ----------------------------------------------------------------------------
diff --git a/doc/eva/main.tex b/doc/eva/main.tex
index b3c5be5239cf7e0bf761765a6392fc75349eacc3..fc9d9c1af019942617ce5a4bc107308f39f54d86 100644
--- a/doc/eva/main.tex
+++ b/doc/eva/main.tex
@@ -4203,13 +4203,13 @@ Most domains are also presented in more details in the following subsections.
     \tabularnewline
     \midrule
     octagon & d-octagon & \ref{sec:octagons} &
-    Infers relations between scalar variables. \\
-    Efficient but limited.
+    Infers relations of the form $l \leq \pm X \pm Y \leq u$ between integer or
+    pointer lvalues. Efficient.
     \tabularnewline
     \midrule
     multidim & d-multidim & \ref{sec:multidim} &
     More precise representation of arrays of structures,
-    multidimensional arrays and arrays invariants. \\
+    multidimensional arrays and arrays invariants.
     Experimental.
     \tabularnewline
     \midrule
@@ -4435,7 +4435,8 @@ and \texttt{y} is not affine.
 
 Activating option \texttt{-eva-domains octagon} instructs Eva to infer relations
 between variables as numerical constraints of the form $l \leq \pm X \pm Y \leq
-u$, where $X$ and $Y$ are program variables, and $l$ and $u$ are constants.
+u$, where $X$ and $Y$ are program variables or lvalues,
+and $l$ and $u$ are constants.
 
 These relations are then used to evaluate more precisely the possible values
 of an expression involving $X$ and $Y$, or to deduce a reduction of
@@ -4455,16 +4456,23 @@ void main (int y) {
 \end{listing-nonumber}
 
 
-Currently, the octagon domain is fast but has two strong limitations:
+Currently, the octagon domain is fast but has some limitations:
 \begin{itemize}
 \item
-  The domain only infers relations between scalar variables of integer types.
-  It ignores pointers, arrays and structure fields.
+  The domain only infers relations between lvalues of integer or
+  pointer types.
+  It does not support relations between floating-point values.
 \item
   The domain only infers relations between pairs of variables occurring in the
   same instruction, as \lstinline|x = y + k;| or \lstinline|if (x < y + k)|.
   If an instruction involves 3 variables or more, relations are inferred for
   each pair of variables.
+\item
+  The domain has no involved memory model and can only infer and use relations
+  about the syntactic lvalues as they appear in the program.
+  For instance, if two pointers \lstinline|p| and \lstinline|q| point to the
+  same location, and a relation is inferred on \lstinline|*p|, the domain cannot
+  use it to improve the value of \lstinline|*q|.
 \end{itemize}
 
 The domain is intraprocedural by default: the inferred relations are local to
@@ -4474,8 +4482,9 @@ to its caller.
 The option \verb+-eva-octagon-through-calls+ makes the octagon domain
 interprocedural, which is a more precise but slower mode where
 the inferred relations are propagated through function calls.
-The analysis of a function can then use the relations inferred in the callers,
-and at the end, the inferred relations are propagated back to the caller.
+The analysis of a function can then use the relations previously inferred in the
+callers, and at the end, the inferred relations are propagated back to the
+caller.
 
 
 \subsection{Multidim}
@@ -5574,7 +5583,11 @@ allocation fails.
 \label{nondeterminism}
 
 The following functions, declared in \lstinline|share/libc/__fc_builtin.h|, allow to
-introduce some non-determinism in the analysis. The results given by
+introduce some non-determinism in the analysis.
+These functions are not specific to \Eva{}; their ACSL specifications
+(omitted here for brevity) can be understood by other \FramaC plug-ins.
+
+The results given by
 \Eva{} are
 valid \textbf{for all values proposed by the user}, as opposed
 to what a test-generation tool would typically do. A tool based
@@ -5590,31 +5603,55 @@ int Frama_C_nondet(int a, int b);
 void *Frama_C_nondet_ptr(void *a, void *b);
     /* returns either a or b */
 
+void Frama_C_make_unknown(char *p, size_t l);
+    /* assigns an arbitrary value to each byte between *p and *(p+l-1) */
+
 int Frama_C_interval(int min, int max);
-    /* returns any value in the interval from min to max inclusive */
+    /* returns any int value in the interval from min to max inclusive */
 
 float Frama_C_float_interval(float min, float max);
-    /* returns any value in the interval from min to max inclusive */
+    /* returns any float value in the interval from min to max inclusive */
 
 double Frama_C_double_interval(double min, double max);
-    /* returns any value in the interval from min to max inclusive */
+    /* returns any double value in the interval from min to max inclusive */
 \end{listing-nonumber}
 
-The implementation of these functions might change in future versions
-of Frama-C, but their types and their behavior will stay the same.
+A series of functions equivalent to \lstinline|Frama_C_interval|
+is defined for other integer and floating-point types:
+they generate ranges containing all values between their two arguments
+(\texttt{min} and \texttt{max}, inclusive) for the given type.
+Here is a complete list of these functions:
+
+\begin{table}[!ht]
+  \centering
+  \begin{tabular}{ll}
+    \lstinline|Frama_C_unsigned_char_interval| &
+    \lstinline|Frama_C_char_interval| \\
+    \lstinline|Frama_C_unsigned_short_interval| &
+    \lstinline|Frama_C_short_interval| \\
+    \lstinline|Frama_C_unsigned_int_interval| &
+    \lstinline|Frama_C_int_interval| \\
+    \lstinline|Frama_C_unsigned_long_interval| &
+    \lstinline|Frama_C_long_interval| \\
+    \lstinline|Frama_C_unsigned_long_long_interval| &
+    \lstinline|Frama_C_long_long_interval| \\
+    \lstinline|Frama_C_interval| (synonym of \lstinline|Frama_C_int_interval|) &
+    \lstinline|Frama_C_size_t_interval| \\
+    \lstinline|Frama_C_float_interval| &
+    \lstinline|Frama_C_double_interval| \\
+    \lstinline|Frama_C_real_interval_as_double|
+  \end{tabular}
+\end{table}
 
 Example of use of the functions introducing non-determinism:
 \csource{examples/nondet.c}
 
 With the command below, the obtained result for
-variable \lstinline|X| is \lstinline|[-45..150],0%3|.
+variable \lstinline|X| is \lstinline|[-45..150],0%3|, and for the
+array \lstinline|arr|, \lstinline|[0..19] ∈ [--..--]|.
 \begin{frama-c-commands}
-frama-c -eva ex_nondet.c .../share/libc/__fc_builtin.c
+frama-c -eva ex_nondet.c
 \end{frama-c-commands}
-The inclusion of \lstinline|.../share/libc/__fc_builtin.c| is only required
-when using the functions \lstinline|Frama_C_float_interval| and
-\lstinline|Frama_C_double_interval|. Otherwise, including the file
-\lstinline|__fc_builtin.h| is sufficient.
 
 Note that reads of volatile variables also return a non-deterministic
 value.
diff --git a/doc/frama-c-book.cls b/doc/frama-c-book.cls
index 93ad4c82df983532f19de21c25b4498bf5483100..3436b3c0c2628484ed962268e2149f9f701725c9 100644
--- a/doc/frama-c-book.cls
+++ b/doc/frama-c-book.cls
@@ -432,6 +432,7 @@
 \definecolor{lstmodule}{rgb}{0.3,0.6,0.2}
 \definecolor{lstspecial}{rgb}{0.2,0.6,0.0}
 \definecolor{lstfile}{gray}{0.85}
+\definecolor{lstcomments}{rgb}{0.35,0.35,0.35}
 
 \newcommand{\lstbrk}{\mbox{$\color{blue}\scriptstyle\cdots$}}
 
@@ -439,7 +440,7 @@
 \def\lp@inline{\ifmmode\normalfont\mathtt\scriptstyle\else\normalfont\ttfamily\mdseries\normalsize\fi}
 \def\lp@keyword{}
 \def\lp@special{\color{frama-c-dark-orange}}
-\def\lp@comment{\normalfont\ttfamily\mdseries}
+\def\lp@comment{\normalfont\ttfamily\mdseries\color{lstcomments}}
 \def\lp@string{\color{frama-c-dark-green}}
 \def\lp@ident{}
 \def\lp@number{\rmfamily\tiny\color{lstnum}\noncopynumber}
@@ -614,17 +615,18 @@
     {é}{{\'e}}1%
   ,
   style=frama-c-style,%
-  morekeywords={
-    action, alias, as, deps, dune, executable, files, flags, from,
-    generate_opam_files, install, lang, libraries, library, name, optional,
-    package, plugin, progn, public_name, rule, section, select, site,
-    targets, using
+  alsoletter=:-,%
+  keywords={%
+    action,alias,as,backend,context,default,deps,dune,executable,%
+    env,env-vars,files,flags,from,generate_opam_files,install,%
+    instrument_with,instrumentation,lang,libraries,library,name,optional,%
+    package,plugin,profile,progn,public_name,rule,section,select,site,%
+    targets,using%
   },%
-  alsoletter=:,
-  morekeywords=[2]{
-    :standard
-  },
-  morecomment=[l]{;},
+  morekeywords=[2]{%
+    :standard%
+  },%
+  morecomment=[l]{;},%
 }
 
 \lstdefinestyle{dune-basic}{%
diff --git a/doc/release/branch.tex b/doc/release/branch.tex
index 7313f46e5b9f437eb76841a23cb2e767432b599d..3c3f9d5943ddb7d0263b27b5b822b22dde8941a9 100644
--- a/doc/release/branch.tex
+++ b/doc/release/branch.tex
@@ -61,63 +61,28 @@ Check public issue tracker at \url{https://git.frama-c.com/pub/frama-c/issues/}.
 All issues should have been at least acknowledged: at least they should be
 assigned to someone, preferably tagged appropriately.
 
-Send a message to the Frama-C channel on LSL's Mattermost.
-Each developer should have a
-look at their own assigned/monitored/reported issues. Depending on their severity,
-the issues should be tagged with the current release, or with the next one.
+Send a message to the Frama-C channel on LSL's Mattermost. Each developer should
+have a look at their own assigned/monitored/reported issues. Depending on their
+severity, the issues should be tagged with the current release, or with the next
+one.
 
-\section{Changelog}
+\section{Version}
 
-Create headers in the Changelog(s). This is to avoid some merge conflicts,
-but also so that merge requests add information in the proper part of
-the Changelog.
-
-\begin{itemize}
-\item Add the following in the Changelogs, in \texttt{stable/element}
-\begin{verbatim}
- ####################################
- Open Source Release <nb> (<element>)
- ####################################
-\end{verbatim}
-
-This should go directly below
-\begin{verbatim}
- ##################################
- Open Source Release <next-release>
- ##################################
-\end{verbatim}
-
-The changelogs to update are the global Frama-C changelog and each plugin
-changelog in \texttt{src/plugins}.
-
-\item Check the manuals if they contain a changelog, usually in files named
-\texttt{changes.tex} or a variation of it. Add the following in
-\texttt{stable/element}
-\begin{verbatim}
-\section*{<nb> (<element>)}
-\end{verbatim}
-
-This should go directly below
+Execute the script:
 \begin{verbatim}
-\section*{\framacversion}
+./dev/set-version.sh NN.M # to be replaced with actual major/minor version
 \end{verbatim}
-and this line should be commented out.
-
+This will:
 \begin{itemize}
-  \item \emph{Take care to adapt the format of the version according to the
-        content of the file}.
-  \item \emph{Check for manual changelogs in \texttt{doc/}, but also in
-        \texttt{src/plugins/**/doc}}.
-\end{itemize}
-
-\item Merge this branch in \texttt{master}
+  \item update the \texttt{Changelog}s
+  \item update the changes in the manuals (excluding ACSL and E-ACSL references)
+  \item update the \texttt{VERSION} and \texttt{VERSION\_CODENAME} files
+  \item update the \texttt{opam} file
+  \item update the API doc
 \end{itemize}
 
-From now on, Changelog items corresponding to MR merged into \texttt{master}
-must be placed between these two banners. This should minimize conflicts when
-merging back \texttt{stable/element} into \texttt{master}.
-
-\todo{Can we simplify this?}
+Merge the branch in \texttt{master} and add a commit to \texttt{master} by
+adding \texttt{"+dev"} in the \texttt{VERSION} file.
 
 \section{Copyright}
 
diff --git a/doc/release/deploy.tex b/doc/release/deploy.tex
index 1de8304b27dacdfe3eebfff7b12998008f035a17..962db136ff2c9399e0ed7ae9011356ad0930cb1f 100644
--- a/doc/release/deploy.tex
+++ b/doc/release/deploy.tex
@@ -150,10 +150,6 @@ Check if other \FramaC (and related) repositories need to be updated:
 \item other \texttt{pub} repositories related to Frama-C...
 \end{itemize}
 
-\section{Preparing the Next Release}
-
-Just update the \texttt{VERSION} file in \texttt{master}, by adding \texttt{"+dev"}.
-
 \section{Docker image preparation}
 
 \textbf{Note:} you need access to the \texttt{framac} Docker Hub account to be
diff --git a/doc/release/validation.tex b/doc/release/validation.tex
index fd9ccc5fe0b912b7d783f7ceb074d0a0487e6a18..bc6ee9d90e10ef028896fa022a20e70cc9aea92c 100644
--- a/doc/release/validation.tex
+++ b/doc/release/validation.tex
@@ -46,25 +46,8 @@ Change version and codename in the following files:
   \end{itemize}
 \end{itemize}
 
-Also check the headers in Changelogs :
-\begin{itemize}
-  \item \texttt{Changelog}
-  \item \texttt{src/plugins/wp/Changelog}
-  \item \texttt{src/plugins/e-acsl/doc/Changelog}
-\end{itemize}
-
 \subsection{Versions in source: API documentation}
 
-To update the \textsf{API} documentation, you must update the \texttt{@since}
-tags. This involves the following script (\texttt{sed -i} must work for this
-purpose):
-\begin{shell}
-./dev/update_api_doc.sh <NEXT>
-\end{shell}
-\verb+<NEXT>+ is the long name of the final release, i.e.
-\verb+`cat VERSION`-`VERSION_CODENAME`+
-(without the \verb+beta+ suffix, if any).
-
 Check that no \verb|+dev| suffix remains inside comments:
 
 \begin{shell}
diff --git a/doc/userman/user-changes.tex b/doc/userman/user-changes.tex
index 2c9097889fe6b3eab1e7409d805cf593136f4890..f5f6cc841c170e5783f3034849f6e508ecf700f7 100644
--- a/doc/userman/user-changes.tex
+++ b/doc/userman/user-changes.tex
@@ -3,8 +3,11 @@
 This chapter summarizes the changes in this documentation between each \FramaC
 release. First we list changes of the last release.
 
-\section*{Frama-C+dev}
+%\section*{Frama-C+dev}
+
+\section*{27.0 (Cobalt)}
 \begin{itemize}
+\item \textbf{Normalizing the Source Code:} new usage of \texttt{-machdep}
 \item \textbf{Normalizing the Source Code:} deprecated option \texttt{-c11}
   (enabled by default).
 \end{itemize}
diff --git a/doc/userman/user-sources.tex b/doc/userman/user-sources.tex
index b748156775df3412b336012ef6b37269a5608bef..b2256fa875b8c8d2cfdd7ed539652bfd0db76be3 100644
--- a/doc/userman/user-sources.tex
+++ b/doc/userman/user-sources.tex
@@ -296,8 +296,11 @@ The list of supported platforms can be obtained by typing:
 \$ frama-c -machdep help
 \end{frama-c-commands}
 
-The process for adding a new platform is described in the Plug-in
-Development Guide~\cite{plugin-dev-guide}.
+Apart from these default platforms, it is possible to give as argument
+to \texttt{-machdep} option the path of a YAML file containing the information
+needed by \FramaC. The Plug-in Development Guide~\cite{plugin-dev-guide} describes
+this format in more detail, as well as the use of the \texttt{make\_machdep.py}
+script to automatically generate it.
 
 \item \optiondef{-}{simplify-cfg} allows \FramaC to remove break, continue and
   switch statements. This option is automatically set by some plug-ins that
diff --git a/headers/headache_config.txt b/headers/headache_config.txt
index 1b9796eb7a29140f1deeb877ca7f8aef54a17006..da136e6e52e5e19823c90dfa5eb466551f0e30a0 100644
--- a/headers/headache_config.txt
+++ b/headers/headache_config.txt
@@ -58,6 +58,8 @@
 ########
 | "dune-project"  -> frame open:";;" line:";" close:";;"
 | ".*dune-project" -> skip match:"(lang.*"
+| "dune-workspace.*" -> frame open:";;" line:";" close:";;"
+| ".*dune-workspace.*" -> skip match:"(lang.*"
 | "dune"          -> frame open:";;" line:";" close:";;"
 
 ############
diff --git a/ivette/.eslintrc.js b/ivette/.eslintrc.js
index 3c9037c5af45b12f4b943734ed882bf55333d240..b2580f8d832220299877a3d52e9e4a436e1f22f0 100644
--- a/ivette/.eslintrc.js
+++ b/ivette/.eslintrc.js
@@ -52,6 +52,41 @@ module.exports = {
     // Disallow the use of console.* to prevent the release of code producing
     // various debuging messages
     "no-console": "error",
+    // Enforce consistent spacing after the // or /* in a comment
+    "spaced-comment": ["error", "always"],
+    // Enforce consistent spacing before and after the arrow in arrow functions
+    "arrow-spacing": "error",
+    // Enforce spaces inside of blocks after opening block and
+    // before closing block
+    "block-spacing": "error",
+    // Enforce consistent spacing before and after commas
+    "comma-spacing": "error",
+    // Enforce consistent newlines before and after dots
+    "dot-location": ["error", "property"],
+    // Require newline at the end of files
+    "eol-last": "error",
+    // Disallow spacing between function identifiers and their invocations
+    "func-call-spacing": "error",
+    // Enforce consistent spacing between keys and values in object literal
+    // properties
+    "key-spacing": "error",
+    // Disallow trailing whitespace at the end of lines
+    "no-trailing-spaces": "error",
+    // Enforce consistent spacing inside braces
+    "object-curly-spacing": ["error", "always"],
+    // Enforce consistent spacing before and after semicolons
+    "semi-spacing": "error",
+    // Enforce location of semicolons
+    "semi-style": "error",
+    // Enforce spacing around colons of switch statements
+    "switch-colon-spacing": "error",
+    // Enforce consistent spacing before blocks
+    "space-before-blocks": "error",
+    // Enforce consistent spacing before function definition opening parenthesis
+    "space-before-function-paren": [
+      "error",
+      {"anonymous": "always", "named": "never", "asyncArrow": "always"}
+    ], 
 
     // --- Safety rules ---
 
diff --git a/ivette/.gitignore b/ivette/.gitignore
index 5137465dd358ebe9aa0f203fc100c0b4cae255b5..08b3cc95e60a655d4d140fb6f410ec9dbedb4ebc 100644
--- a/ivette/.gitignore
+++ b/ivette/.gitignore
@@ -9,7 +9,6 @@
 .eslint-cache
 node_modules
 yarn-error.log
-/bin
 /dist
 /doc/html
 /src/renderer/loader.ts
diff --git a/ivette/Makefile b/ivette/Makefile
index 84dc2b6ad5acadfdc84b34dcd8cd4d92a1f949b9..4ce870bd17cd216d2c1b257e1bc808f81ac78f8e 100644
--- a/ivette/Makefile
+++ b/ivette/Makefile
@@ -23,9 +23,9 @@
 # --------------------------------------------------------------------------
 APP=Ivette
 DOME=./src/dome
-DOME_ARGS=--command $$(dirname $$0)/../../bin/frama-c
+DOME_ARGS=--command $$(dirname $$0)/frama-c
 DOME_DEV=-server-debug 1
-DOME_CLI=./bin/ivette
+DOME_CLI=../bin/ivette
 DOME_API=./src/frama-c
 DOME_CUSTOM_ENTRIES= yes
 COPYRIGHT=CEA LIST / LSL
@@ -35,21 +35,34 @@ COPYRIGHT=CEA LIST / LSL
 # --- Ivette Compilation
 # --------------------------------------------------------------------------
 
-.PHONY: all app dev lint checkcase tsc
+.PHONY: all app dev
 
-all: pkg lint app
+all: pkg check-lint app
 
-app: dome-app
-dev: dome-dev
+app: api dome-app
+dev: api dome-dev
 
-lint: dome-pkg dome-templ checkcase
+# --------------------------------------------------------------------------
+# --- Ivette Linting
+# --------------------------------------------------------------------------
+
+.PHONY: lint check-lint check-case
+
+# With autofix
+lint: dome-pkg dome-templ check-case
+	@echo "[Ivette] running typechecker & linter (with cache & fix mode)"
+	yarn run typecheck
+	yarn run lint --fix --cache --cache-location .eslint-cache
+
+# Without autofix
+check-lint: dome-pkg dome-templ check-case
 	@echo "[Ivette] running typechecker & linter"
 	yarn run typecheck
 	yarn run lint
 
 # In case-insensitive filesystems (macOS/Windows), import statements and
 # filenames can have issues due to case differences
-checkcase:
+check-case:
 	@echo "[Ivette] check case issues in imported filenames"
 	@err=0 ; for f in `find src | sed -E 's/(.ts|.tsx|.js|.jsx|.css|.json)$$//' | sort -f | uniq -di` ;\
 	 do \
@@ -58,11 +71,6 @@ checkcase:
 	 done ;\
 	 exit $$err
 
-tsc: dome-pkg dome-templ
-	@echo "[Ivette] running typechecker & linter (with cache & fix mode)"
-	yarn run typecheck
-	yarn run lint --fix --cache --cache-location .eslint-cache
-
 # --------------------------------------------------------------------------
 # --- Help
 # --------------------------------------------------------------------------
@@ -75,14 +83,15 @@ help::
 # --- Ivette Distribution
 # --------------------------------------------------------------------------
 
-.PHONY: dist dist-dir
+.PHONY: dist appimage dist-dir
+
+dist: dist-dir dome-dist
+appimage: dist-dir dome-appimage
 
 dist-dir:
 	@echo "Cleaning dist"
 	@rm -fr dist
 
-dist: dist-dir dome-dist
-
 # --------------------------------------------------------------------------
 # --- Ivette Package Loader
 # --------------------------------------------------------------------------
@@ -94,11 +103,11 @@ SANDBOX=src/renderer/sandbox.ts
 PACKAGES=$(shell find src -name "pkg.json")
 SANDBOXES=$(shell find src/sandbox -name "*.tsx")
 
-lint: pkg
 dome-pkg: pkg
 dome-app: pkg
 dome-dev: pkg
 dome-dist: pkg
+dome-appimage: pkg
 
 pkg: $(LOADER) $(SANDBOX)
 
@@ -118,7 +127,7 @@ $(SANDBOX): $(SANDBOXES) ./sandboxer.js ./Makefile
 # --- Frama-C API
 # --------------------------------------------------------------------------
 
-.PHONY: api
+.PHONY: api check-api
 
 api:
 	@echo "[Ivette] Generating TypeScript API"
diff --git a/ivette/electron-builder.json b/ivette/electron-builder.json
index ff7514100edc044947d80466558bcb99ea87c78c..4c25993d65459fa61fc90f665c5fe0714788554f 100644
--- a/ivette/electron-builder.json
+++ b/ivette/electron-builder.json
@@ -1,5 +1,9 @@
 {
   "productName": "Ivette",
   "mac": { "icon": "icon.icns" },
-  "linux": { "icon": "icon.png" }
+  "linux": {
+    "icon": "icon.png",
+    "target": "appImage",
+    "category": "Developpement"
+  }
 }
diff --git a/ivette/ivette-bootstrap.sh b/ivette/ivette-bootstrap.sh
index 5ce9ba70657d986e5fcfde39fca87290fa614b23..7ab111cffcb3cb46eefcd2b8a65c5b04648bc2ad 100755
--- a/ivette/ivette-bootstrap.sh
+++ b/ivette/ivette-bootstrap.sh
@@ -87,15 +87,15 @@ fi
 echo "[2/3] Compiling Ivette"
 # --------------------------------------------------------------------------
 
-TMPDIR=`mktemp -d`
-cd $TMPDIR
+IVETTE_TMP_DIR=`mktemp -d`
+cd $IVETTE_TMP_DIR
 tar zxf $PREFIX/lib/frama-c/ivette.tgz
 cd ivette
 make dist
 if [ "$?" != "0" ]
 then
     echo "Compilation Failed"
-    rm -fr $TMPDIR
+    rm -fr $IVETTE_TMP_DIR
     exit 2
 fi
 
@@ -107,11 +107,11 @@ make PREFIX=$PREFIX install
 if [ "$?" != "0" ]
 then
     echo "Installation Failed"
-    rm -fr $TMPDIR
+    rm -fr $IVETTE_TMP_DIR
     exit 3
 fi
 cd $USERCWD
-rm -fr $TMPDIR
+rm -fr $IVETTE_TMP_DIR
 rm -f $PREFIX/lib/frama-c/ivette.tgz
 
 # --------------------------------------------------------------------------
diff --git a/ivette/package.json b/ivette/package.json
index 665132667063b1add37e44d44a1309a4b11c2ab2..a5f9526ccad99ede1383d421c93c9a10281b8d4d 100644
--- a/ivette/package.json
+++ b/ivette/package.json
@@ -5,6 +5,7 @@
   "repository": "git@git.frama-c.com:frama-c/Ivette.git",
   "author": "Loïc Correnson <loic.correnson@cea.fr>",
   "license": "MIT",
+  "description": "Frama-C GUI",
   "scripts": {
     "lint": "eslint --ext .ts,.tsx --format=compact ./src",
     "typecheck": "tsc --noEmit",
diff --git a/ivette/src/dome/main/dome.ts b/ivette/src/dome/main/dome.ts
index d32c37a3f9c3c371a5705628c5dd8acb56865dab..993f45c5bdd104cb3bbe59bad0220b97631643ca 100644
--- a/ivette/src/dome/main/dome.ts
+++ b/ivette/src/dome/main/dome.ts
@@ -477,10 +477,22 @@ function createBrowserWindow(
   });
 
   // Emitted when the window want's to close.
-  theWindow.on('close', () => {
+  const closeHandler = function (event: Event): void {
+    // Do not call this handler in a cycle; the next close event will forcibly
+    // close the window
+    theWindow.off('close', closeHandler);
+    // Do not close the window yet
+    event.preventDefault();
+
     handle.frame = theWindow.getBounds();
     handle.devtools = webContents.isDevToolsOpened();
     webContents.send('dome.ipc.closing');
+  };
+
+  theWindow.on('close', closeHandler);
+
+  ipcMain.on('dome.ipc.closing.done', () => {
+    theWindow.close();
   });
 
   // Keep track of frame positions (in DEVEL)
@@ -501,8 +513,15 @@ function createBrowserWindow(
 // --- Application Window(s) & Command Line
 // --------------------------------------------------------------------------
 
-function stripElectronArgv(argv: string[]): string[] {
-  return argv.slice(DEVEL ? 3 : (LOCAL ? 2 : 1)).filter((p) => !!p);
+interface Cmd { wdir: string; argv: string[] }
+
+function stripElectronArgv(cmd: Cmd): Cmd
+{
+  const wdir = DEVEL ? cmd.argv[3] : cmd.wdir;
+  const argv = cmd.argv
+      .slice(DEVEL ? 4 : (LOCAL ? 2 : 1))
+      .filter((p) => !!p && p !== "--no-sandbox");
+  return { wdir, argv };
 }
 
 function createPrimaryWindow(): void {
@@ -516,14 +535,14 @@ function createPrimaryWindow(): void {
     });
   const cwd = process.cwd();
   const wdir = cwd === '/' ? app.getPath('home') : cwd;
-  const argv = stripElectronArgv(process.argv);
+  const cmd = stripElectronArgv({ wdir, argv: process.argv });
 
   // Initialize Theme
   const globals = obtainGlobalSettings();
   applyThemeSettings(globals);
 
   // Create Window
-  createBrowserWindow(true, { title: appName }, argv, wdir);
+  createBrowserWindow(true, { title: appName }, cmd.argv, cmd.wdir);
 }
 
 let appCount = 1;
@@ -538,9 +557,9 @@ function createSecondaryWindow(
   if (argString) {
     argString = argString.substring(argStart.length);
     const electronArgv = JSON.parse(argString);
-    const argv = stripElectronArgv(electronArgv);
+    const cmd = stripElectronArgv({ wdir, argv: electronArgv });
     const title = `${appName} #${++appCount}`;
-    createBrowserWindow(false, { title }, argv, wdir);
+    createBrowserWindow(false, { title }, cmd.argv, cmd.wdir);
   }
 }
 
@@ -624,6 +643,8 @@ ipcMain.on('dome.app.paths', (event) => {
 // --- Main Application Starter
 // --------------------------------------------------------------------------
 
+let isQuitting = false;
+
 /** Starts the main process. */
 export function start(): void {
 
@@ -643,6 +664,11 @@ export function start(): void {
   app.on('activate', activateWindows); // Mac OSX response to dock
   app.on('second-instance', createSecondaryWindow);
 
+  // Configuring macOS for exiting
+  app.on('before-quit', () => {
+    isQuitting = true;
+  });
+
   // At-exit callbacks
   app.on('will-quit', () => {
     saveGlobalSettings();
@@ -654,7 +680,7 @@ export function start(): void {
   // Warning: when no event handler is registered, the app automatically
   // quit when all windows are closed.
   app.on('window-all-closed', () => {
-    if (System.platform !== 'macos') app.quit();
+    if (isQuitting || System.platform !== 'macos') app.quit();
   });
 
 }
diff --git a/ivette/src/dome/misc/system.ts b/ivette/src/dome/misc/system.ts
index f97d6e7760df5f02ba7cc2a1860290ec7b03bcea..d3c6f8e5a7f6c01cfae4946ba67ec25d644d47d4 100644
--- a/ivette/src/dome/misc/system.ts
+++ b/ivette/src/dome/misc/system.ts
@@ -114,7 +114,7 @@ emitter.setMaxListeners(250);
 // --- At Exit
 // --------------------------------------------------------------------------
 
-export type Callback = () => void;
+export type Callback = () => (void | Promise<void>);
 
 const exitJobs: Callback[] = [];
 
@@ -128,11 +128,14 @@ export function atExit(callback: Callback): void {
 }
 
 /** Execute all pending exit jobs (and flush the list). */
-export function doExit(): void {
-  exitJobs.forEach((fn) => {
-    try { fn(); }
+export async function doExit(): Promise<void> {
+  await Promise.all(exitJobs.map(async (fn) => {
+    try {
+      const promise = fn();
+      promise && await promise;
+    }
     catch (err) { D.error('atExit:', err); }
-  });
+  }));
   exitJobs.length = 0;
 }
 
@@ -144,6 +147,7 @@ let COMMAND_WDIR = '.';
 let COMMAND_ARGV: string[] = [];
 
 function setCommandLine(argv: string[], wdir: string): void {
+  process.chdir(wdir);
   COMMAND_ARGV = argv;
   COMMAND_WDIR = wdir;
 }
@@ -464,13 +468,16 @@ export function rename(oldPath: string, newPath: string): Promise<void> {
 
 const childprocess = new Map<number, Exec.ChildProcess>();
 
-atExit(() => {
-  childprocess.forEach((process, pid) => {
-    try { process.kill(); }
+atExit(async () => {
+  await Promise.all(Array.from(childprocess.values()).map(async (process) => {
+    try {
+      process.kill();
+      await new Promise(resolve => process.on('exit', resolve));
+    }
     catch (err) {
-      D.warn('killing process', pid, err);
+      D.warn('killing process', process.pid, err);
     }
-  });
+  }));
 });
 
 export type StdPipe = { path?: string | undefined; mode?: number; pipe?: boolean };
diff --git a/ivette/src/dome/renderer/controls/buttons.tsx b/ivette/src/dome/renderer/controls/buttons.tsx
index e15fd0dbf4ef2131ed0f3103942862b8b1fae1c7..461524e30851a5c20e8b4812f4602e8bc3558f90 100644
--- a/ivette/src/dome/renderer/controls/buttons.tsx
+++ b/ivette/src/dome/renderer/controls/buttons.tsx
@@ -555,10 +555,9 @@ export interface FieldProps {
    Text Field.
 */
 export const Field = (props: FieldProps): JSX.Element => {
-  const [current, setCurrent] = React.useState<string>();
   const { className = '', onChange, onEdited, value = '' } = props;
+  const [current, setCurrent] = React.useState<string>(value);
   const disabled = onChange ? DISABLED(props) : true;
-  const theValue = current ?? value;
   const ONCHANGE = (evt: React.ChangeEvent<HTMLInputElement>): void => {
     const text = evt.target.value || '';
     setCurrent(text);
@@ -567,11 +566,11 @@ export const Field = (props: FieldProps): JSX.Element => {
   const ONKEYPRESS = (evt: React.KeyboardEvent): void => {
     switch (evt.key) {
       case 'Enter':
-        setCurrent(undefined);
-        if (onChange && current) onChange(current);
+        if (onChange) onChange(current);
         break;
       case 'Escape':
-        setCurrent(undefined);
+        setCurrent(value);
+        if (onChange) onChange(value);
         break;
       default:
         break;
@@ -582,12 +581,12 @@ export const Field = (props: FieldProps): JSX.Element => {
       id={props.id}
       type="text"
       autoFocus={!disabled && props.autoFocus}
-      value={theValue}
+      value={current}
       className={`dome - xField ${className} `}
       style={props.style}
       disabled={disabled}
       placeholder={props.placeholder}
-      onKeyPress={ONKEYPRESS}
+      onKeyDown={ONKEYPRESS}
       onChange={ONCHANGE}
     />
   );
diff --git a/ivette/src/dome/renderer/controls/labels.tsx b/ivette/src/dome/renderer/controls/labels.tsx
index 382828a4f5c78b4f33db1ee8f59ec57516807a4d..9bf33338966698005165edb522aa0d29f9b38c42 100644
--- a/ivette/src/dome/renderer/controls/labels.tsx
+++ b/ivette/src/dome/renderer/controls/labels.tsx
@@ -63,8 +63,7 @@ export interface LabelProps {
 }
 
 const makeLabel = (className: string) =>
-  function Label
-    (
+  function Label(
       props: LabelProps,
       ref: LegacyRef<HTMLLabelElement> | undefined
     ): JSX.Element {
diff --git a/ivette/src/dome/renderer/dark.css b/ivette/src/dome/renderer/dark.css
index 0660868825afc53f7e051a476f593e2d9c4d15f6..cbe9a2b73b54eb26904eb96adbb7a80fef9c2000 100644
--- a/ivette/src/dome/renderer/dark.css
+++ b/ivette/src/dome/renderer/dark.css
@@ -10,8 +10,8 @@
     --code-hover: #005137;
     --code-select: #4f3d24;
     --code-select-hover: #5f4d34;
-    --dead-code: #444;
-    --non-terminating: #444;
+    --dead-code: #777;
+    --non-terminating: #d84954;
     --highlighted-marker: #778822;
     --code-bullet: #0a2234;
 
diff --git a/ivette/src/dome/renderer/data/arrays.ts b/ivette/src/dome/renderer/data/arrays.ts
index a0db9f45a15e5b2df7fd218b48f7f5087d9b1d0a..994b261ac7006840e7e7fb2126447648799ab3a7 100644
--- a/ivette/src/dome/renderer/data/arrays.ts
+++ b/ivette/src/dome/renderer/data/arrays.ts
@@ -59,7 +59,7 @@ export function merge<K, A extends K, B extends K>(
   f: (x : K) => unknown,
 ): (A & (object | B))[] {
   const dict = new Map(a2.map(x2 => [f(x2), x2])); // maps f(x2) to x2
-  return a1.map(x1 => ({...x1, ...(dict.get(f(x1)))}));
+  return a1.map(x1 => ({ ...x1, ...(dict.get(f(x1))) }));
 }
 
 /** Maps a function through an array and returns the first computed value that
diff --git a/ivette/src/dome/renderer/data/json.ts b/ivette/src/dome/renderer/data/json.ts
index 11f7a039384b5a76bcf6a106b9b096adc4c44825..f323711d086a5d0eeb077441ebaba7b95f9951d1 100644
--- a/ivette/src/dome/renderer/data/json.ts
+++ b/ivette/src/dome/renderer/data/json.ts
@@ -200,7 +200,7 @@ export const jInt: Decoder<number> = (js: json) => {
     return js;
   }
   else {
-    throw new JsonTypeError("integer", js); 
+    throw new JsonTypeError("integer", js);
   }
 };
 
@@ -215,7 +215,7 @@ export const jBoolean: Decoder<boolean> = (js: json) => {
     return js;
   }
   else {
-    throw new JsonTypeError("boolean", js); 
+    throw new JsonTypeError("boolean", js);
   }
 };
 
@@ -235,10 +235,10 @@ export const jString: Decoder<string> = (js: json) => {
       return js;
     }
     else {
-      throw new JsonTypeError("string", js); 
+      throw new JsonTypeError("string", js);
     }
   };
-  
+
 
 /** JSON constant.
     Capture the tag or throw JsonError.
@@ -251,7 +251,7 @@ export function jTag<A>(tg: A): Decoder<A> {
       return tg;
     }
     else {
-      throw new JsonTypeError(`"${tg}"`, js); 
+      throw new JsonTypeError(`"${tg}"`, js);
     }
   };
 }
@@ -589,7 +589,7 @@ export function jKey<K>(kd: K): Decoder<key<K>> {
       return forge(kd, js);
     }
     else {
-      throw new JsonTypeError(`key<${kd}>`, js); 
+      throw new JsonTypeError(`key<${kd}>`, js);
     }
   };
 }
@@ -601,7 +601,7 @@ export function jIndex<K>(kd: K): Decoder<index<K>> {
       return forge(kd, js);
     }
     else {
-      throw new JsonTypeError(`index<${kd}>`, js); 
+      throw new JsonTypeError(`index<${kd}>`, js);
     }
   };
 }
diff --git a/ivette/src/dome/renderer/dnd.tsx b/ivette/src/dome/renderer/dnd.tsx
index d1ad128c736e3b4cb70ecaa5f78b8b717b6e012b..7a7643036414ad413d4390591b88866760a92535 100644
--- a/ivette/src/dome/renderer/dnd.tsx
+++ b/ivette/src/dome/renderer/dnd.tsx
@@ -352,14 +352,14 @@ export interface DragSourceProps extends DragHandler, DropHandler {
    as a Drop Target into the DnD controller.
  */
 export function DragSource(props: DragSourceProps): JSX.Element {
-  //--- Props
+  // --- Props
   const { dnd, disabled = false, handle, children } = props;
   const { onStart, onDrag, onStop } = props;
-  //--- Dragging State
+  // --- Dragging State
   const [dragging, setDragging] = React.useState<Dragging | undefined>();
-  //--- Dropping Ref
+  // --- Dropping Ref
   const nodeRef = useDropTarget(dnd, disabled ? undefined : props);
-  //--- onStart
+  // --- onStart
   const handleStart: DraggableEventHandler = React.useCallback(
     (_, { x, y, node }) => {
       if (dnd && nodeRef.current)
@@ -371,7 +371,7 @@ export function DragSource(props: DragSourceProps): JSX.Element {
       });
       if (onStart) onStart();
     }, [dnd, nodeRef, onStart]);
-  //--- onDrag
+  // --- onDrag
   const handleDrag: DraggableEventHandler = React.useCallback(
     (e, { x, y }) => {
       if (e && dnd) dnd.handleEvent(e);
@@ -381,14 +381,14 @@ export function DragSource(props: DragSourceProps): JSX.Element {
         if (onDrag) onDrag(newDragging);
       }
     }, [dnd, dragging, onDrag]);
-  //--- onStop
+  // --- onStop
   const handleStop: DraggableEventHandler = React.useCallback(
     () => {
       if (dnd) dnd.handleDrop();
       setDragging(undefined);
       if (onStop) onStop();
     }, [dnd, onStop]);
-  //--- Renderer
+  // --- Renderer
   const render = RenderOverlay(props, dragging);
   return (
     <DraggableCore
@@ -447,25 +447,25 @@ export interface ItemProps {
    item contents is rendered inside a `<DragSource/>` component automatically
    connected to the englobing `<List/>` DnD controller.  */
 export function Item(props: ItemProps): JSX.Element {
-  //--- Ordering
+  // --- Ordering
   const { dnd, items, setSource, setTarget, onStop } =
     React.useContext(CurrentList);
   const { id, className, children } = props;
   const order = getItem(items, id);
-  //--- D&D Events
+  // --- D&D Events
   const onStart = React.useCallback(() => {
     if (setSource) setSource(id);
   }, [setSource, id]);
   const onDropIn = React.useCallback(() => {
     if (setTarget) setTarget(id);
   }, [setTarget, id]);
-  //--- Styling
+  // --- Styling
   const style = styles(
     props.style,
     order < 0 && { display: 'none' },
     0 <= order && { order },
   );
-  //--- Rendering
+  // --- Rendering
   return (
     <DragSource
       className={className}
diff --git a/ivette/src/dome/renderer/dome.tsx b/ivette/src/dome/renderer/dome.tsx
index 2a19d1ec505a951e43a8e91d7537234c94b6146d..d05bbd025647811411d424b51848735991eb3992 100644
--- a/ivette/src/dome/renderer/dome.tsx
+++ b/ivette/src/dome/renderer/dome.tsx
@@ -251,10 +251,13 @@ export const globalSettings = new Event(Settings.global);
 // --- Closing
 // --------------------------------------------------------------------------
 
-ipcRenderer.on('dome.ipc.closing', System.doExit);
+ipcRenderer.on('dome.ipc.closing', async () => {
+    await System.doExit();
+    ipcRenderer.send('dome.ipc.closing.done');
+  });
 
 /** Register a callback to be executed when the window is closing. */
-export function atExit(callback: () => void): void {
+export function atExit(callback: () => (void | Promise<void>)): void {
   System.atExit(callback);
 }
 
@@ -603,7 +606,7 @@ export function usePromise<A>(job: Promise<A>): PromiseHook<A> {
     let c = false;
     const set = (x?: A, e?: Error): void => { setResult(x); setError(e); };
     const doCancel = (): boolean => { if (!c) setLoading(false); return c; };
-    const onResult = (x: A): void => { if (!doCancel()) set(x, undefined);};
+    const onResult = (x: A): void => { if (!doCancel()) set(x, undefined); };
     const onError = (e: Error): void => { if (!doCancel()) set(undefined, e); };
     job.then(onResult, onError);
     return () => { c = true; };
diff --git a/ivette/src/dome/renderer/frame/sidebars.tsx b/ivette/src/dome/renderer/frame/sidebars.tsx
index f0bab90f7187001cfcc7513e79538a2ad1dd82d2..f7b332affdf2e55298907c528465e9bbbf934171 100644
--- a/ivette/src/dome/renderer/frame/sidebars.tsx
+++ b/ivette/src/dome/renderer/frame/sidebars.tsx
@@ -34,7 +34,7 @@ import { useFlipSettings } from 'dome';
 import { Badge } from 'dome/controls/icons';
 import { Label } from 'dome/controls/labels';
 import { classes } from 'dome/misc/utils';
-import { Hbox, Hfill } from 'dome/layout/boxes';
+import { Hbox } from 'dome/layout/boxes';
 import { IconButton, IconButtonProps } from 'dome/controls/buttons';
 
 import './style.css';
@@ -110,6 +110,8 @@ export interface SectionProps {
   disabled?: boolean;
   /** Badge summary (only visible when folded). */
   summary?: Badges;
+  /** Additional label, right-aligned. */
+  infos?: string;
   /** Additional controls, (only visible when unfolded). */
   rightButtonProps?: IconButtonProps;
   /** Section contents. */
@@ -129,7 +131,7 @@ export interface SectionProps {
    Sections with no items are not displayed.
 */
 export function Section(props: SectionProps): JSX.Element | null {
-  const { settings, defaultUnfold, unfold } = props;
+  const { settings, defaultUnfold, infos, unfold } = props;
   const [state, flipState] = useFlipSettings(settings, defaultUnfold);
   const icon = state ? 'TRIANGLE.DOWN' : 'TRIANGLE.RIGHT';
 
@@ -145,15 +147,14 @@ export function Section(props: SectionProps): JSX.Element | null {
 
   return (
     <div className={`dome-xSideBarSection ${props.className}`}>
-      <Hbox>
+      <Hbox className='dome-xSideBarSection-title' >
         <Label
-          className='dome-xSideBarSection-title dome-color-frame'
           title={props.title}
           label={props.label}
           icon={icon}
           onClick={flipState}
         />
-        <Hfill />
+        {infos && <div className='dome-xSideBarSection-infos'>{infos}</div>}
         {visible ? rightButton : makeBadge(props.summary)}
       </Hbox>
       <div className='dome-xSideBarSection-content' style={{ maxHeight }}>
diff --git a/ivette/src/dome/renderer/frame/style.css b/ivette/src/dome/renderer/frame/style.css
index ed917a3189b1e5a241f3c41a399c2b7c7b439ecb..6ee566c0a2684df21fb5c9704a0d216e157a29f9 100644
--- a/ivette/src/dome/renderer/frame/style.css
+++ b/ivette/src/dome/renderer/frame/style.css
@@ -90,8 +90,7 @@
     padding: 0px ;
 }
 
-.dome-xSideBar.dome-color-frame,
-.dome-xSideBarSection-title.dome-color-frame
+.dome-xSideBar.dome-color-frame
 {
     background: var(--background-sidebar) ;
 }
@@ -116,6 +115,7 @@
     display: flex ;
     flex-flow: row nowrap ;
     align-items: center ;
+    background: var(--background-sidebar) ;
 }
 
 .dome-xSideBarSection-title > .dome-xLabel {
@@ -129,9 +129,17 @@
     flex: 0 0 ;
 }
 
+.dome-xSideBarSection-infos {
+    font-size: smaller;
+    color: var(--info-text-discrete);
+    padding-left: 4px;
+    padding-right: 4px;
+    display: block;
+}
+
 .dome-xSideBarSection-filterButton {
   margin: 0px;
-  padding: 0px;
+  padding: 3px;
 }
 
 .dome-xSideBarSection-hideshow {
@@ -162,14 +170,6 @@
   display: flex;
 }
 
-.dome-xSideBarSection-info {
-  color: var(--info-text-discrete);
-  font-style: italic;
-  padding-left: 20px;
-  padding-right: 10px;
-  display: block;
-}
-
 /* -------------------------------------------------------------------------- */
 /* --- SideBar Items                                                      --- */
 /* -------------------------------------------------------------------------- */
@@ -443,16 +443,12 @@
   padding: 0;
   overflow: hidden;
   font-size: 13px;
-  width: 28px;
+  width: 228px;
   border-radius: 12px;
   transition: width 0.4s ease-in-out;
   z-Index: +1;
 }
 
-.dome-xToolBar-actionField:hover {
-  width: 228px;
-}
-
 .dome-xToolBar-actionField:focus-within {
   width: 228px !important;
   box-shadow: 0 0 2px var(--border-discrete);
diff --git a/ivette/src/dome/renderer/layout/qsplit.tsx b/ivette/src/dome/renderer/layout/qsplit.tsx
index ec10dd95311972c827d0b25a2e85de807cc0124c..5241ef0a3ae373ec5e8de5e02f9506b30f940079 100644
--- a/ivette/src/dome/renderer/layout/qsplit.tsx
+++ b/ivette/src/dome/renderer/layout/qsplit.tsx
@@ -307,31 +307,31 @@ function QSplitEngine(props: QSplitEngineProps): JSX.Element {
   const BD = sameOf(B, D);
   const CD = sameOf(C, D);
   const ABCD = fullOf(A, B, C, D);
-  //----------------------------------------
+  // ----------------------------------------
   // [ A ]
-  //---------------------------------------
+  // ---------------------------------------
   if (ABCD) {
     DISPLAY(layout, ABCD, 0, width, 0, height);
   }
-  //----------------------------------------
+  // ----------------------------------------
   // [ A - C ]
-  //---------------------------------------
+  // ---------------------------------------
   else if (AB && CD) {
     vsplit = VSPLIT(0, Y, width);
     DISPLAY(layout, AB, 0, width, 0, Y);
     DISPLAY(layout, CD, 0, width, Y + 1, RY);
   }
-  //----------------------------------------
+  // ----------------------------------------
   // [ A | B ]
-  //---------------------------------------
+  // ---------------------------------------
   else if (AC && BD) {
     hsplit = HSPLIT(X, 0, height);
     DISPLAY(layout, AC, 0, X, 0, height);
     DISPLAY(layout, BD, X + 1, RX, 0, height);
   }
-  //----------------------------------------
+  // ----------------------------------------
   // [ A – C|D ]
-  //----------------------------------------
+  // ----------------------------------------
   else if (AB) {
     hsplit = HSPLIT(X, Y, RY);
     vsplit = VSPLIT(0, Y, width);
@@ -339,9 +339,9 @@ function QSplitEngine(props: QSplitEngineProps): JSX.Element {
     DISPLAY(layout, C, 0, X, Y + 1, RY);
     DISPLAY(layout, D, X + 1, RX, Y + 1, RY);
   }
-  //----------------------------------------
+  // ----------------------------------------
   // [ A | B-D ]
-  //----------------------------------------
+  // ----------------------------------------
   else if (AC) {
     hsplit = HSPLIT(X, 0, height);
     vsplit = VSPLIT(X, Y, RY);
@@ -349,9 +349,9 @@ function QSplitEngine(props: QSplitEngineProps): JSX.Element {
     DISPLAY(layout, B, X + 1, RX, 0, Y);
     DISPLAY(layout, D, X + 1, RX, Y + 1, RY);
   }
-  //----------------------------------------
+  // ----------------------------------------
   // [ A-C | B ]
-  //----------------------------------------
+  // ----------------------------------------
   else if (BD) {
     hsplit = HSPLIT(X, 0, height);
     vsplit = VSPLIT(0, Y, X);
@@ -359,9 +359,9 @@ function QSplitEngine(props: QSplitEngineProps): JSX.Element {
     DISPLAY(layout, BD, X + 1, RX, 0, height);
     DISPLAY(layout, C, 0, X, Y + 1, RY);
   }
-  //----------------------------------------
+  // ----------------------------------------
   // [ A|B - C ]
-  //----------------------------------------
+  // ----------------------------------------
   else if (CD) {
     hsplit = HSPLIT(X, 0, Y);
     vsplit = VSPLIT(0, Y, width);
@@ -369,9 +369,9 @@ function QSplitEngine(props: QSplitEngineProps): JSX.Element {
     DISPLAY(layout, B, X + 1, RX, 0, Y);
     DISPLAY(layout, CD, 0, width, Y + 1, RY);
   }
-  //----------------------------------------
+  // ----------------------------------------
   // [ A, B, C, D ]
-  //----------------------------------------
+  // ----------------------------------------
   else {
     hsplit = HSPLIT(X, 0, height);
     vsplit = VSPLIT(0, Y, width);
@@ -380,12 +380,12 @@ function QSplitEngine(props: QSplitEngineProps): JSX.Element {
     DISPLAY(layout, C, 0, X, Y + 1, RY);
     DISPLAY(layout, D, X + 1, RX, Y + 1, RY);
   }
-  //----------------------------------------
+  // ----------------------------------------
   if (hsplit !== NODISPLAY && vsplit !== NODISPLAY)
     hvsplit = { display: 'block', left: X, top: Y };
-  //----------------------------------------
+  // ----------------------------------------
   // Rendering
-  //----------------------------------------
+  // ----------------------------------------
   return (
     <QSplitContext.Provider value={layout}>
       <BSplitter
diff --git a/ivette/src/dome/renderer/light.css b/ivette/src/dome/renderer/light.css
index 0caf3fb0e549257228f9e19d34c17a8b73f51b34..135bd1ef348473c56143123b5e73d2b6cd9e5c82 100644
--- a/ivette/src/dome/renderer/light.css
+++ b/ivette/src/dome/renderer/light.css
@@ -10,8 +10,8 @@
     --code-hover: lightgreen;
     --code-select: #ffda95;
     --code-select-hover: orange;
-    --dead-code: #bbb;
-    --non-terminating: #bbb;
+    --dead-code: #999;
+    --non-terminating: #fb4e4a;
     --highlighted-marker: #ffff66;
     --code-bullet: #ddd;
 
diff --git a/ivette/src/dome/renderer/table/arrays.ts b/ivette/src/dome/renderer/table/arrays.ts
index 45d3d48bb99709d39c26556b3c684a7f7473d24f..16d1e29ba1fab4d11c435201113488eb2ed505c2 100644
--- a/ivette/src/dome/renderer/table/arrays.ts
+++ b/ivette/src/dome/renderer/table/arrays.ts
@@ -454,6 +454,11 @@ export class ArrayModel<Key, Row>
     this.index.forEach((p) => { fn(p.row); });
   }
 
+  /** Number of non-filtered entries. */
+  length(): number {
+    return this.index.size;
+  }
+
 }
 
 // --------------------------------------------------------------------------
diff --git a/ivette/src/dome/renderer/text/editor.tsx b/ivette/src/dome/renderer/text/editor.tsx
index 7ca40b680eba78057fdd0ce13b21e378afbb86b0..ea59f699394de28ca868c041c3b6b47f03100437 100644
--- a/ivette/src/dome/renderer/text/editor.tsx
+++ b/ivette/src/dome/renderer/text/editor.tsx
@@ -310,13 +310,13 @@ const Highlight = Language.syntaxHighlighting(Language.HighlightStyle.define([
   { tag: tags.typeName, class: 'cm-type' },
   { tag: tags.number, class: 'cm-number' },
   { tag: tags.controlKeyword, class: 'cm-keyword' },
-  { tag: tags.definition(tags.variableName) , class: 'cm-def' },
+  { tag: tags.definition(tags.variableName), class: 'cm-def' },
 ]));
 
 // A language provider based on the [Lezer C++ parser], extended with
 // highlighting and folding information. Only comments can be folded.
 // (Source: https://github.com/lezer-parser/cpp)
-const comment = (t: SyntaxNode): Range => ({ from: t.from + 2, to: t.to - 2});
+const comment = (t: SyntaxNode): Range => ({ from: t.from + 2, to: t.to - 2 });
 const folder = Language.foldNodeProp.add({ BlockComment: comment });
 const stringPrefixes = [ "L", "u", "U", "u8", "LR", "UR", "uR", "u8R", "R" ];
 const cppLanguage = Language.LRLanguage.define({
@@ -432,6 +432,18 @@ export function unfoldAll(view: View): void {
   if (view !== null) Language.unfoldAll(view);
 }
 
+function isVisible(view: View, line: number): boolean {
+  if (!view || view.state.doc.lines < line) return false;
+  const doc = view.state.doc;
+  const top = view.documentTop;
+  const rect = view.dom.getBoundingClientRect();
+  const topVisibleBlock = view.lineBlockAtHeight(rect.top - top);
+  const topVisibleLine = doc.lineAt(topVisibleBlock.to).number;
+  const bottomVisibleBlock = view.lineBlockAtHeight(rect.bottom - top);
+  const bottomVisibleLine = doc.lineAt(bottomVisibleBlock.from).number;
+  return (topVisibleLine < line && line < bottomVisibleLine);
+}
+
 // Move to the given line. The indexation starts at 1.
 export function selectLine(view: View, line: number, atTop: boolean): void {
   if (!view || view.state.doc.lines < line) return;
@@ -439,9 +451,10 @@ export function selectLine(view: View, line: number, atTop: boolean): void {
   const { from: here } = doc.lineAt(view.state.selection.main.from);
   const { from: goto } = doc.line(Math.max(line, 1));
   if (here === goto) return;
-  view.dispatch({ selection: { anchor: goto }, scrollIntoView: true });
-  if (!atTop) return;
-  const effects = EditorView.scrollIntoView(goto, { y: 'start', yMargin: 0 });
+  view.dispatch({ selection: { anchor: goto } });
+  if (isVisible(view, line)) return;
+  const verticalScroll = atTop ? 'start' : 'center';
+  const effects = EditorView.scrollIntoView(goto, { y: verticalScroll });
   view.dispatch({ effects });
 }
 
diff --git a/ivette/src/dome/renderer/text/style.css b/ivette/src/dome/renderer/text/style.css
index a299cc047c2f86f9defd7ed5d4fd6bce27577fa3..3b26fd8a537d41bdaa6ec097adc1eb648e4ce690 100644
--- a/ivette/src/dome/renderer/text/style.css
+++ b/ivette/src/dome/renderer/text/style.css
@@ -183,6 +183,12 @@
   background: var(--code-bullet);
 }
 
+.cm-deadcode-gutter {
+  width: 4px;
+  background: var(--code-bullet);
+  color: var(--dead-code);
+}
+
 .cm-hovered-code {
   background-color: var(--code-hover);
 }
@@ -199,14 +205,12 @@
   background-color: var(--highlighted-marker);
 }
 
-.cm-dead-code {
+:not(.cm-dead-code) > .cm-dead-code {
   font-style: italic;
-  filter: opacity(0.7);
+  filter: opacity(0.5);
 }
 
 .cm-non-term-code {
-  font-style: italic;
-  filter: opacity(0.7);
 }
 
 .cm-tainted {
diff --git a/ivette/src/dome/renderer/themes.tsx b/ivette/src/dome/renderer/themes.tsx
index 9cbccae6908332a555c7033b1eb80a518c57d604..5a21d6b45c1b56c24bbd283d7d658e3f797489c6 100644
--- a/ivette/src/dome/renderer/themes.tsx
+++ b/ivette/src/dome/renderer/themes.tsx
@@ -29,7 +29,7 @@
    @module dome/themes
  */
 
-//import React from 'react';
+// import React from 'react';
 import * as Dome from 'dome';
 import * as Settings from 'dome/data/settings';
 import { State } from 'dome/data/states';
diff --git a/ivette/src/dome/template/makefile b/ivette/src/dome/template/makefile
index b79a6e427570a59875966f7b19825a5aa5039b02..f2545cfde15901a9b3e00086a1e28bc6bb58f398 100644
--- a/ivette/src/dome/template/makefile
+++ b/ivette/src/dome/template/makefile
@@ -25,6 +25,7 @@
 # --------------------------------------------------------------------------
 
 # DOMEMK_ reserved for makefile derived variables
+# CURDIR is a Makefile builtin variable
 
 APP?=$(shell basename $(CURDIR))
 COPYRIGHT?=CEA Tech
@@ -220,10 +221,11 @@ dome-dev: dome-pkg dome-templ
 	@echo "#!/bin/sh" >> $(DOME_CLI)
 	@echo "export DOME='$(DOME)'" >> $(DOME_CLI)
 	@echo "export DOME_ENV='dev'" >> $(DOME_CLI)
-	@echo 'exec $(DOME_MK_BIN)/electron-webpack dev $(DOME_ARGS) $(DOME_DEV) "$$@"' >> $(DOME_CLI)
+	@echo 'WDIR=$$PWD' >> $(DOME_CLI)
+	@echo 'ARGV="$(DOME_ARGS) $(DOME_DEV) $$@"' >> $(DOME_CLI)
+	@echo "cd $(CURDIR)" >> $(DOME_CLI)
+	@echo 'exec $(DOME_MK_BIN)/electron-webpack dev $$WDIR $$ARGV' >> $(DOME_CLI)
 	@chmod 555 $(DOME_CLI)
-	@echo "[Dome] running application (development)"
-	@$(DOME_CLI)
 
 # --------------------------------------------------------------------------
 # ---  Application Building
@@ -246,13 +248,20 @@ dome-app: dome-pkg dome-templ
 # ---  Application Packaging
 # --------------------------------------------------------------------------
 
-.PHONY: dome-dist
+.PHONY: dome-dist dome-appimage
 
+# Compatible with all OS for installation from source
 dome-dist: dome-app
-	@echo "[Dome] packaging application (production)"
+	@echo "[Dome] packaging application (binary)"
 	DOME=$(DOME) yarn run electron-builder --dir -c.compression=store -c.mac.identity=null
 	@echo "[Dome] application packaged in ./dist"
 
+# Build Linux AppImage for binary distribution
+dome-appimage: dome-app
+	@echo "[Dome] packaging application (AppImage)"
+	DOME=$(DOME) yarn run electron-builder --linux -c.compression=store -c.mac.identity=null
+	@echo "[Dome] application packaged in ./dist"
+
 # --------------------------------------------------------------------------
 # --- Icon gallery
 # --------------------------------------------------------------------------
diff --git a/ivette/src/frama-c/kernel/ASTview.tsx b/ivette/src/frama-c/kernel/ASTview.tsx
index c02f1b2fcf9b96ca3f33f2e400cee4112fe707c0..35a124c9ea372b193fc00bb233abbbce9d303283 100644
--- a/ivette/src/frama-c/kernel/ASTview.tsx
+++ b/ivette/src/frama-c/kernel/ASTview.tsx
@@ -49,7 +49,9 @@ import * as Preferences from 'ivette/prefs';
 
 // An alias type for functions and locations.
 type Fct = string | undefined;
-type Marker = string | undefined;
+type Marker = Ast.marker | undefined;
+
+const noMarker = Ast.jMarker('');
 
 // A range is just a pair of position in the code.
 type Range = Editor.Range;
@@ -74,12 +76,12 @@ function mapFilter<A, B>(xs: readonly A[], fn: (x: A) => B | undefined): B[] {
 // without information on the ranges of each element. It will be converted in a
 // good old tree that carry those information.
 interface Leaf extends Range { text: string }
-interface Node extends Range { id: string, children: Tree[] }
+interface Node extends Range { marker: Ast.marker, children: Tree[] }
 type Tree = Leaf | Node;
 
 // Utility functions on trees.
-function isLeaf (t: Tree): t is Leaf { return 'text' in t; }
-function isNode (t: Tree): t is Node { return 'id' in t && 'children' in t; }
+function isLeaf(t: Tree): t is Leaf { return 'text' in t; }
+function isNode(t: Tree): t is Node { return 'marker' in t && 'children' in t; }
 const empty: Tree = { text: '', from: 0, to: 0 };
 
 // Convert an Ivette text (i.e a function's code) into a Tree, adding range
@@ -98,7 +100,7 @@ function textToTree(t: text): Tree | undefined {
       if (node) children.push(node);
       acc = to;
     }
-    return [{ id: t[0], from, to: acc, children }, acc];
+    return [{ marker: Ast.jMarker(t[0]), from, to: acc, children }, acc];
   }
   const [res] = aux(t, 0);
   return res;
@@ -116,13 +118,13 @@ function textToString(text: text): string {
 
 // Computes, for each markers of a tree, its range. Returns the map containing
 // all those bindings.
-function markersRanges(tree: Tree): Map<string, Range[]>{
+function markersRanges(tree: Tree): Map<string, Range[]> {
   const ranges: Map<string, Range[]> = new Map();
   const toRanges = (tree: Tree): void => {
     if (!isNode(tree)) return;
-    const trees = ranges.get(tree.id) ?? [];
+    const trees = ranges.get(tree.marker) ?? [];
     trees.push(tree);
-    ranges.set(tree.id, trees);
+    ranges.set(tree.marker, trees);
     for (const child of tree.children) toRanges(child);
   };
   toRanges(tree);
@@ -159,7 +161,7 @@ const Text = Editor.createTextField<text>(null, textToString);
 
 // This aspect computes the tree representing the currently displayed function's
 // code, represented by the <Text> field.
-const Tree = Editor.createAspect({ t: Text }, ({t}) => rootText(t));
+const Tree = Editor.createAspect({ t: Text }, ({ t }) => rootText(t));
 
 // This aspect computes the markers ranges of the currently displayed function's
 // tree, represented by the <Tree> aspect.
@@ -198,8 +200,8 @@ function createMarkerUpdater(): Editor.Extension {
   return Editor.createEventHandler(deps, {
     mouseup: ({ fct, tree, update }, view, event) => {
       const main = view.state.selection.main;
-      const id = coveringNode(tree, main.from)?.id;
-      const location = { fct, marker: Ast.jMarker(id) };
+      const marker = coveringNode(tree, main.from)?.marker;
+      const location = { fct, marker };
       update({ location });
       if (event.altKey) States.MetaSelection.emit(location);
     }
@@ -217,7 +219,8 @@ function createMarkerScroller(): Editor.Extension {
     const markerRanges = ranges.get(marker) ?? [];
     if (markerRanges.length !== 1) return;
     const { from: anchor } = markerRanges[0];
-    view.dispatch({ selection: { anchor }, scrollIntoView: true });
+    const line = view.state.doc.lineAt(anchor).number;
+    Editor.selectLine(view, line, false);
   });
 }
 
@@ -235,7 +238,7 @@ const Hovered = Editor.createField<Marker>(undefined);
 // The Ivette hovered element must be updated by CodeMirror plugins. This
 // field add the callback in the CodeMirror internal state.
 type UpdateHovered = (h: States.Hovered) => void;
-const UpdateHovered = Editor.createField<UpdateHovered>(() => { return ; });
+const UpdateHovered = Editor.createField<UpdateHovered>(() => { return; });
 
 // The Hovered field is updated each time the mouse moves through the CodeMirror
 // document. The handlers updates the Ivette hovered information, which is then
@@ -263,7 +266,7 @@ function createHoveredUpdater(): Editor.Extension {
       const horizontallyOk = left <= coords.x && coords.x <= right;
       const verticallyOk = top <= coords.y && coords.y <= bottom;
       if (!horizontallyOk || !verticallyOk) { reset(); return; }
-      const marker = Ast.jMarker(hov.id);
+      const marker = hov.marker;
       updateHovered(marker ? { fct, marker } : undefined);
     }
   });
@@ -322,18 +325,68 @@ function createMultipleDecorator(): Editor.Extension {
 const emptyDeadCode = { unreachable: [], nonTerminating: [] };
 const Dead = Editor.createField<Eva.deadCode>(emptyDeadCode);
 
+const UnreachableRanges = createUnreachableRanges();
+function createUnreachableRanges(): Editor.Aspect<Editor.Range[]> {
+  const deps = { dead: Dead, ranges: Ranges };
+  return Editor.createAspect(deps, ({ dead, ranges }) => {
+    return mapFilter(dead.unreachable, m => ranges.get(m)).flat();
+  });
+}
+
+const NonTerminatingRanges = createNonTerminatingRanges();
+function createNonTerminatingRanges(): Editor.Aspect<Editor.Range[]> {
+  const deps = { dead: Dead, ranges: Ranges };
+  return Editor.createAspect(deps, ({ dead, ranges }) => {
+    return mapFilter(dead.nonTerminating, m => ranges.get(m)).flat();
+  });
+}
+
 const DeadCodeDecorator = createDeadCodeDecorator();
 function createDeadCodeDecorator(): Editor.Extension {
-  const uClass = Editor.Decoration.mark({ class: 'cm-dead-code' });
-  const tClass = Editor.Decoration.mark({ class: 'cm-non-term-code' });
-  const deps = { dead: Dead, ranges: Ranges };
-  return Editor.createDecorator(deps, ({ dead, ranges }) => {
-    const range = (m: string): Range[] | undefined => ranges.get(m);
-    const unreachableRanges = mapFilter(dead.unreachable, range).flat();
-    const unreachable = unreachableRanges.map(r => uClass.range(r.from, r.to));
-    const nonTermRanges = mapFilter(dead.nonTerminating, range).flat();
-    const nonTerm = nonTermRanges.map(r => tClass.range(r.from, r.to));
-    return Editor.RangeSet.of(unreachable.concat(nonTerm), true);
+  const uCls = Editor.Decoration.mark({ class: 'cm-dead-code' });
+  const tCls = Editor.Decoration.mark({ class: 'cm-non-term-code' });
+  const deps = { unreach: UnreachableRanges, nonTerm: NonTerminatingRanges };
+  return Editor.createDecorator(deps, ({ unreach, nonTerm }) => {
+    const unreachable = unreach.map(r => uCls.range(r.from, r.to));
+    const nonTerminating = nonTerm.map(r => tCls.range(r.from, r.to));
+    return Editor.RangeSet.of(unreachable.concat(nonTerminating), true);
+  });
+}
+
+type DeadCodeKind = 'unreachable' | 'non terminating';
+class DeadCodeGutterMarker extends Editor.GutterMarker {
+  readonly element: HTMLDivElement;
+  toDOM(): HTMLDivElement { return this.element; }
+  constructor(kind: DeadCodeKind) {
+    super();
+    const color = kind === 'unreachable' ? 'dead-code' : 'non-terminating';
+    this.element = document.createElement('div');
+    this.element.innerHTML = 'a';
+    this.element.title = `This code is ${kind}`;
+    this.element.style.width = '4px';
+    this.element.style.color = `var(--${color})`;
+    this.element.style.borderRight = `4px solid var(--${color})`;
+  }
+}
+
+const DeadCodeGutter = createDeadCodeGutter();
+function createDeadCodeGutter(): Editor.Extension {
+  const deps = { unreach: UnreachableRanges, nonTerm: NonTerminatingRanges };
+  const cls = 'cm-deadcode-gutter';
+  return Editor.createGutter(deps, cls, (props, block, view) => {
+    const doc = view.state.doc;
+    const line = doc.lineAt(block.from);
+    const unreachable = props.unreach
+      .filter(r => r.from <= doc.length)
+      .map(r => ({ from: doc.lineAt(r.from).from, to: doc.lineAt(r.to).to }))
+      .find(r => r.from <= line.from && line.to <= r.to);
+    if (unreachable) return new DeadCodeGutterMarker('unreachable');
+    const nonTerm = props.nonTerm
+      .filter(r => r.from <= doc.length)
+      .map(r => ({ from: doc.lineAt(r.from).from, to: doc.lineAt(r.to).to }))
+      .find(r => r.from <= line.from && line.to <= r.to);
+    if (nonTerm) return new DeadCodeGutterMarker('non terminating');
+    return null;
   });
 }
 
@@ -357,7 +410,7 @@ function getPropertiesNodes(tree: Tree): Node[] {
   if (isLeaf(tree)) return [];
   /* Must be consistent with the id chosen by the Frama-C server for property
      markers. Ideally, this test should not depend on markers id syntax. */
-  if (tree.id.startsWith('#p')) return [tree];
+  if (tree.marker.startsWith('#p')) return [tree];
   return tree.children.map(getPropertiesNodes).flat();
 }
 
@@ -369,7 +422,7 @@ function createPropertiesNodes() : Editor.Aspect<Property[]> {
   return Editor.createAspect(deps, ({ tree, tags, statuses }) => {
     const nodes = getPropertiesNodes(tree);
     return mapFilter(nodes, (n) => {
-      const s = statuses.find((s) => s.key === n.id);
+      const s = statuses.find((s) => s.key === n.marker);
       if (!s) return undefined;
       const tag = tags.get(s.status);
       if (!tag) return undefined;
@@ -480,23 +533,27 @@ async function studia(props: StudiaProps): Promise<StudiaInfos> {
 // This field contains all the current function's callers, as inferred by Eva.
 const Callers = Editor.createField<Eva.CallSite[]>([]);
 
+// This field contains the function pointed to by the current hovered marker,
+// as inferred by Eva.
+const Callees = Editor.createField<Fct[]>([]);
+
 // This field contains information on markers.
-type GetMarkerData = (key: string) => Ast.markerAttributesData | undefined;
+type GetMarkerData = (key: Ast.marker) => Ast.markerAttributesData | undefined;
 const GetMarkerData = Editor.createField<GetMarkerData>(() => undefined);
 
 const ContextMenuHandler = createContextMenuHandler();
 function createContextMenuHandler(): Editor.Extension {
-  const data = { tree: Tree, callers: Callers };
+  const data = { tree: Tree, callers: Callers, callees: Callees };
   const deps = { ...data, update: UpdateSelection, getData: GetMarkerData };
   return Editor.createEventHandler(deps, {
     contextmenu: (inputs, view, event) => {
-      const { tree, callers, update, getData } = inputs;
+      const { tree, callers, callees, update, getData } = inputs;
       const coords = { x: event.clientX, y: event.clientY };
       const position = view.posAtCoords(coords); if (!position) return;
       const node = coveringNode(tree, position);
-      if (!node || !node.id) return;
+      if (!node || !node.marker) return;
       const items: Dome.PopupMenuItem[] = [];
-      const attrs = getData(node.id);
+      const attrs = getData(node.marker);
       if (attrs?.isFunDecl) {
         const groupedCallers = Lodash.groupBy(callers, (cs) => cs.kf);
         const locations =
@@ -519,15 +576,27 @@ function createContextMenuHandler(): Editor.Extension {
         const label = `Go to definition of ${attrs.name}`;
         items.push({ label, onClick });
       }
+      else if (attrs?.isFunctionPointer) {
+        Lodash.forEach(callees, (fct) => {
+          const onClick = (): void => update({ location: { fct } });
+          const label = `Go to definition of ${fct} (indirect)`;
+          items.push({ label, onClick });
+        });
+      }
       const enabled = attrs?.isLval;
       const onClick = (kind: access): void => {
-        if (attrs && node.id)
-          studia({ marker: node.id, attrs, kind }).then(update);
+        if (attrs && node.marker)
+          studia({ marker: node.marker, attrs, kind }).then(update);
       };
       const reads = 'Studia: select reads';
       const writes = 'Studia: select writes';
       items.push({ label: reads, enabled, onClick: () => onClick('Reads') });
       items.push({ label: writes, enabled, onClick: () => onClick('Writes') });
+      const copy = (): void => {
+        const text = view.state.sliceDoc(node.from, node.to);
+        if (text !== '') navigator.clipboard.writeText(text);
+      };
+      items.push({ label: 'Copy to clipboard', onClick: copy });
       if (items.length > 0) Dome.popupMenu(items);
       return;
     }
@@ -617,6 +686,11 @@ function useFctCallers(fct: Fct): Eva.CallSite[] {
   return States.useRequest(Eva.getCallers, fct) ?? [];
 }
 
+// Server request handler returning the given function's callers.
+function useCallees(marker: Marker): Fct[] {
+  return States.useRequest(Eva.getCallees, marker || undefined) ?? [];
+}
+
 // Server request handler returning the tainted lvalues.
 function useFctTaints(fct: Fct): Eva.LvalueTaints[] {
   return States.useRequest(Eva.taintedLvalues, fct, { onError: [] }) ?? [];
@@ -641,6 +715,7 @@ const extensions: Editor.Extension[] = [
   DeadCodeDecorator,
   ContextMenuHandler,
   PropertiesGutter,
+  DeadCodeGutter,
   TaintedLvaluesDecorator,
   TaintTooltip,
   Editor.ReadOnly,
@@ -665,11 +740,12 @@ export default function ASTview(): JSX.Element {
 
   // Updating CodeMirror when the <updateHovered> callback is changed.
   const [hov, setHov] = States.useHovered();
+  const hovered = hov?.marker ?? noMarker;
   React.useEffect(() => UpdateHovered.set(view, setHov), [view, setHov]);
-  React.useEffect(() => Hovered.set(view, hov?.marker ?? ''), [view, hov]);
+  React.useEffect(() => Hovered.set(view, hovered), [view, hovered]);
 
   // Updating CodeMirror when the <properties> synchronized array is changed.
-  const props = States.useSyncArray(Properties.status).getArray();
+  const props = States.useSyncArrayData(Properties.status);
   React.useEffect(() => PropertiesStatuses.set(view, props), [view, props]);
 
   // Updating CodeMirror when the <propStatusTags> map is changed.
@@ -677,8 +753,7 @@ export default function ASTview(): JSX.Element {
   React.useEffect(() => Tags.set(view, tags), [view, tags]);
 
   // Updating CodeMirror when the <markersInfo> synchronized array is changed.
-  const info = States.useSyncArray(Ast.markerAttributes);
-  const getData = React.useCallback((key) => info.getData(key), [info]);
+  const getData = States.useSyncArrayGetter(Ast.markerAttributes);
   React.useEffect(() => GetMarkerData.set(view, getData), [view, getData]);
 
   // Retrieving data on currently selected function and updating CodeMirror when
@@ -692,6 +767,10 @@ export default function ASTview(): JSX.Element {
   const taints = useFctTaints(fct);
   React.useEffect(() => TaintedLvalues.set(view, taints), [view, taints]);
 
+  // Retrieving data on currently hovered marker.
+  const callees = useCallees(hovered);
+  React.useEffect(() => Callees.set(view, callees), [view, callees]);
+
   return (
     <>
       <TitleBar>
@@ -712,7 +791,7 @@ export default function ASTview(): JSX.Element {
         />
         <Inset />
       </TitleBar>
-      <Component style={{ fontSize: `${fontSize}px`}} />
+      <Component style={{ fontSize: `${fontSize}px` }} />
     </>
   );
 }
diff --git a/ivette/src/frama-c/kernel/Globals.tsx b/ivette/src/frama-c/kernel/Globals.tsx
index 78d4ed4189b20acb235ceade6a25abcee4018bdd..827957171c9f59670571422193e636da8544c890 100644
--- a/ivette/src/frama-c/kernel/Globals.tsx
+++ b/ivette/src/frama-c/kernel/Globals.tsx
@@ -32,8 +32,6 @@ import { alpha } from 'dome/data/compare';
 import { Section, Item } from 'dome/frame/sidebars';
 import { Button } from 'dome/controls/buttons';
 import * as Toolbars from 'dome/frame/toolbars';
-import * as Models from 'dome/table/models';
-import * as Arrays from 'dome/table/arrays';
 
 import * as States from 'frama-c/states';
 import * as Kernel from 'frama-c/kernel/api/ast';
@@ -106,15 +104,13 @@ type functionsData =
 type FctKey = Json.key<'#functions'>;
 
 function computeFcts(
-  ker: Arrays.CompactModel<FctKey,Kernel.functionsData>,
-  eva: Arrays.CompactModel<FctKey,Eva.functionsData>,
-  _kstamp: number,
-  _estamp: number,
+  ker: States.ArrayProxy<FctKey, Kernel.functionsData>,
+  eva: States.ArrayProxy<FctKey, Eva.functionsData>,
 ): functionsData[] {
   const arr: functionsData[] = [];
   ker.forEach((kf) => {
     const ef = eva.getData(kf.key);
-    arr.push({...ef,...kf});
+    arr.push({ ...ef, ...kf });
   });
   return arr.sort((f, g) => alpha(f.name, g.name));
 }
@@ -123,25 +119,28 @@ export default function Globals(): JSX.Element {
 
   // Hooks
   const [selection, updateSelection] = States.useSelection();
-  const kerFcts = States.useSyncArray(Kernel.functions);
-  const evaFcts = States.useSyncArray(Eva.functions);
-  const kerStamp = Models.useModel(kerFcts);
-  const evaStamp = Models.useModel(evaFcts);
-  const fcts = React.useMemo(
-    () => computeFcts(kerFcts,evaFcts,kerStamp,evaStamp),
-    [kerFcts,evaFcts,kerStamp,evaStamp]
-  );
+  const ker = States.useSyncArrayProxy(Kernel.functions);
+  const eva = States.useSyncArrayProxy(Eva.functions);
+  const fcts = React.useMemo(() => computeFcts(ker, eva), [ker, eva]);
   const { useFlipSettings } = Dome;
   const [stdlib, flipStdlib] =
     useFlipSettings('ivette.globals.stdlib', false);
   const [builtin, flipBuiltin] =
     useFlipSettings('ivette.globals.builtin', false);
+  const [def, flipDef] =
+    useFlipSettings('ivette.globals.def', true);
   const [undef, flipUndef] =
     useFlipSettings('ivette.globals.undef', true);
-  const [selected, flipSelected] =
-    useFlipSettings('ivette.globals.selected', false);
-  const [evaOnly, flipEvaOnly] =
-    useFlipSettings('ivette.globals.evaonly', false);
+  const [intern, flipIntern] =
+    useFlipSettings('ivette.globals.intern', true);
+  const [extern, flipExtern] =
+    useFlipSettings('ivette.globals.extern', true);
+  const [evaAnalyzed, flipEvaAnalyzed] =
+    useFlipSettings('ivette.globals.eva-analyzed', true);
+  const [evaUnreached, flipEvaUnreached] =
+    useFlipSettings('ivette.globals.eva-unreached', true);
+    const [selected, flipSelected] =
+      useFlipSettings('ivette.globals.selected', false);
   const multipleSelection = selection?.multiple;
   const multipleSelectionActive = multipleSelection?.allSelections.length > 0;
   const evaComputed = States.useSyncValue(computationState) === 'computed';
@@ -159,11 +158,16 @@ export default function Globals(): JSX.Element {
     const visible =
       (stdlib || !fct.stdlib)
       && (builtin || !fct.builtin)
+      && (def || !fct.defined)
       && (undef || fct.defined)
-      && (!evaOnly || !evaComputed ||
+      && (intern || fct.extern)
+      && (extern || !fct.extern)
+      && (evaAnalyzed || !evaComputed ||
+        !('eva_analyzed' in fct && fct.eva_analyzed === true))
+      && (evaUnreached || !evaComputed ||
         ('eva_analyzed' in fct && fct.eva_analyzed === true))
       && (!selected || !multipleSelectionActive || isSelected(fct));
-    return visible || (!!current && fct.name === current);
+    return !!visible;
   }
 
   function onSelection(name: string): void {
@@ -182,24 +186,48 @@ export default function Globals(): JSX.Element {
         checked: stdlib,
         onClick: flipStdlib,
       },
+      'separator',
+      {
+        label: 'Show defined functions',
+        checked: def,
+        onClick: flipDef,
+      },
       {
         label: 'Show undefined functions',
         checked: undef,
         onClick: flipUndef,
       },
       'separator',
+      {
+        label: 'Show non-extern functions',
+        checked: intern,
+        onClick: flipIntern,
+      },
+      {
+        label: 'Show extern functions',
+        checked: extern,
+        onClick: flipExtern,
+      },
+      'separator',
+      {
+        label: 'Show functions analyzed by Eva',
+        enabled: evaComputed,
+        checked: evaAnalyzed,
+        onClick: flipEvaAnalyzed,
+      },
+      {
+        label: 'Show functions unreached by Eva',
+        enabled: evaComputed,
+        checked: evaUnreached,
+        onClick: flipEvaUnreached,
+      },
+      'separator',
       {
         label: 'Selected only',
         enabled: multipleSelectionActive,
         checked: selected,
         onClick: flipSelected,
       },
-      {
-        label: 'Analyzed by Eva only',
-        enabled: evaComputed,
-        checked: evaOnly,
-        onClick: flipEvaOnly,
-      },
     ];
     Dome.popupMenu(items);
   }
@@ -229,15 +257,15 @@ export default function Globals(): JSX.Element {
 
   const noFunction =
     <div className='dome-xSideBarSection-content'>
-      <label className='dome-xSideBarSection-info'>
-        {'There is no function to display.'}
+      <label className='globals-info'>
+        There is no function to display.
       </label>
     </div>;
 
   const allFiltered =
     <div className='dome-xSideBarSection-content'>
-      <label className='dome-xSideBarSection-info'>
-        {'All functions are filtered. Try adjusting function filters.'}
+      <label className='globals-info'>
+        All functions are filtered. Try adjusting function filters.
       </label>
       <Button {...filterButtonProps} label='Functions filters' />
     </div>;
diff --git a/ivette/src/frama-c/kernel/Messages.tsx b/ivette/src/frama-c/kernel/Messages.tsx
index b1b64a290679d8398443d117bc6ec6ad3ba4a857..d635b8fa23449d2a3661fc008177daf3b796ff1c 100644
--- a/ivette/src/frama-c/kernel/Messages.tsx
+++ b/ivette/src/frama-c/kernel/Messages.tsx
@@ -81,6 +81,7 @@ const kindFilter: KindFilter = {
    messages. They are all shown by default. */
 const pluginFilter: PluginFilter = {
   'aorai': true,
+  'cg': true,
   'dive': true,
   'e-acsl': true,
   'eva': true,
@@ -426,7 +427,7 @@ export default function RenderMessages(): JSX.Element {
     return m;
   });
 
-  const data = States.useSyncArray(Kernel.message).getArray();
+  const data = States.useSyncArrayData(Kernel.message);
 
   React.useEffect(() => {
     model.removeAllData();
@@ -455,7 +456,7 @@ export default function RenderMessages(): JSX.Element {
       selectMsg(msg);
       setText(msg.message);
       if (msg.fct && msg.marker) {
-        const location = { fct:msg.fct, marker:msg.marker };
+        const location = { fct: msg.fct, marker: msg.marker };
         updateSelection({ location });
       }
     }, [updateSelection],
diff --git a/ivette/src/frama-c/kernel/Properties.tsx b/ivette/src/frama-c/kernel/Properties.tsx
index 81d95fd79304c40ea31f29e735797659ca125438..1e32d93af70b1e7c10f85fd7a94e6b938d906064 100644
--- a/ivette/src/frama-c/kernel/Properties.tsx
+++ b/ivette/src/frama-c/kernel/Properties.tsx
@@ -38,7 +38,8 @@ import * as Models from 'dome/table/models';
 import * as Arrays from 'dome/table/arrays';
 import { Table, Column, ColumnProps, Renderer } from 'dome/table/views';
 import { TitleBar } from 'ivette';
-import { Scroll, Folder } from 'dome/layout/boxes';
+import { Scroll } from 'dome/layout/boxes';
+import { Section } from 'dome/frame/sidebars';
 
 import { RSplit } from 'dome/layout/splitters';
 
@@ -81,8 +82,8 @@ const DEFAULTS: { [key: string]: boolean } = {
   'kind.axiomatic': true,
   'kind.pragma': true,
   'kind.others': true,
-  'alarms.alarms': true, // show properties that are alarms
-  'alarms.others': true, // show properties that are not alarms
+  'source.alarms': true, // show properties that are alarms
+  'source.others': true, // show properties that are not alarms
   'alarms.overflow': true,
   'alarms.division_by_zero': true,
   'alarms.mem_access': true,
@@ -121,6 +122,31 @@ function useFilter(path: string): [boolean, () => void] {
   );
 }
 
+function resetFilters(prefix: string, b?: boolean) : void {
+  for (const key in DEFAULTS) {
+    if (key.startsWith(prefix)) {
+      const target = b ?? DEFAULTS[key];
+      const path = `ivette.properties.filter.${key}`;
+      Settings.setWindowSettings(path, target);
+    }
+  }
+  Reload.emit();
+}
+
+function filterSummary(prefix: string) : string {
+  let total = 0;
+  let enabled = 0;
+  for (const key in DEFAULTS) {
+    if (key.startsWith(prefix)) {
+      total ++;
+      if (filter(key)) enabled++;
+    }
+  }
+  if (enabled === 0) return 'none';
+  if (enabled === total) return 'all';
+  return `${enabled} / ${total}`;
+}
+
 function filterStatus(
   status: Properties.propStatus,
 ): boolean {
@@ -174,7 +200,7 @@ function filterKind(
 
 function filterAlarm(alarm: string | undefined): boolean {
   if (alarm) {
-    if (!filter('alarms.alarms')) return false;
+    if (!filter('source.alarms')) return false;
     switch (alarm) {
       case 'overflow': return filter('alarms.overflow');
       case 'division_by_zero': return filter('alarms.division_by_zero');
@@ -196,7 +222,7 @@ function filterAlarm(alarm: string | undefined): boolean {
       default: return false;
     }
   }
-  return filter('alarms.others');
+  return filter('source.others');
 }
 
 function filterEva(p: Property): boolean {
@@ -367,20 +393,51 @@ const Reload = new Dome.Event('ivette.properties.reload');
 
 interface SectionProps {
   label: string;
+  prefix?: string;
   unfold?: boolean;
   children: React.ReactNode;
 }
 
-function Section(props: SectionProps): JSX.Element {
+async function onContextMenu(prefix:string): Promise<void> {
+  const items: Dome.PopupMenuItem[] = [
+    {
+      label: 'Reset to default',
+      onClick: () => resetFilters(prefix),
+    },
+    {
+      label: 'Select all',
+      onClick: () => resetFilters(prefix, true),
+    },
+    {
+      label: 'Deselect all',
+      onClick: () => resetFilters(prefix, false),
+    },
+  ];
+  Dome.popupMenu(items);
+}
+
+function FilterSection(props: SectionProps): JSX.Element {
   const settings = `properties-section-${props.label}`;
+  const { label, prefix } = props;
+  const filterButtonProps =
+    prefix ? {
+      icon: 'TUNINGS',
+      title: `Configure filters`,
+      onClick: () => onContextMenu(prefix),
+    } : undefined;
+  const update = Dome.useForceUpdate();
+  Settings.useWindowSettingsEvent(update);
+  const summary = prefix ? filterSummary(prefix) : undefined;
   return (
-    <Folder
-      label={props.label}
+    <Section
+      label={label}
       settings={settings}
       defaultUnfold={props.unfold}
+      infos={summary}
+      rightButtonProps={filterButtonProps}
     >
       {props.children}
-    </Folder>
+    </Section>
   );
 }
 
@@ -414,7 +471,7 @@ function PropertyFilter(): JSX.Element {
   return (
     <Scroll>
       <CheckField label="Current function" path="currentFunction" />
-      <Section label="Status" unfold>
+      <FilterSection label="Status" prefix="status" unfold>
         <CheckField label="Valid" path="status.valid" />
         <CheckField label="Valid under hyp." path="status.valid_hyp" />
         <CheckField label="Unknown" path="status.unknown" />
@@ -424,8 +481,8 @@ function PropertyFilter(): JSX.Element {
         <CheckField label="Untried" path="status.untried" />
         <CheckField label="Dead" path="status.dead" />
         <CheckField label="Inconsistent" path="status.inconsistent" />
-      </Section>
-      <Section label="Property kind">
+      </FilterSection>
+      <FilterSection label="Property kind" prefix="kind">
         <CheckField label="Assertions" path="kind.assert" />
         <CheckField label="Invariants" path="kind.invariant" />
         <CheckField label="Variants" path="kind.variant" />
@@ -441,12 +498,12 @@ function PropertyFilter(): JSX.Element {
         <CheckField label="Pragma" path="kind.pragma" />
         <CheckField label="Assumes" path="kind.assumes" />
         <CheckField label="Others" path="kind.others" />
-      </Section>
-      <Section label="Alarms">
-        <CheckField label="Alarms" path="alarms.alarms" />
-        <CheckField label="Others" path="alarms.others" />
-      </Section>
-      <Section label="Alarms kind">
+      </FilterSection>
+      <FilterSection label="Source" prefix="source">
+        <CheckField label="Alarms" path="source.alarms" />
+        <CheckField label="Others" path="source.others" />
+      </FilterSection>
+      <FilterSection label="Alarms kind" prefix="alarms">
         <CheckField label="Overflows" path="alarms.overflow" />
         <CheckField label="Divisions by zero" path="alarms.division_by_zero" />
         <CheckField label="Shifts" path="alarms.shift" />
@@ -463,8 +520,8 @@ function PropertyFilter(): JSX.Element {
         <CheckField label="Differing blocks" path="alarms.differing_blocks" />
         <CheckField label="Separations" path="alarms.separation" />
         <CheckField label="Overlaps" path="alarms.overlap" />
-      </Section>
-      <Section label="Eva">
+      </FilterSection>
+      <FilterSection label="Eva">
         <CheckField
           label="High-priority only"
           path="eva.priority_only"
@@ -480,7 +537,7 @@ function PropertyFilter(): JSX.Element {
           path="eva.ctrl_tainted_only"
           title="Show only control-tainted properties according to the Eva taint domain"
         />
-      </Section>
+      </FilterSection>
     </Scroll>
   );
 }
@@ -597,8 +654,8 @@ function FilterRatio({ model }: { model: PropertyModel }): JSX.Element {
 // --- Properties Table
 // -------------------------------------------------------------------------
 
-type PropsModel = Arrays.CompactModel<PropKey,Properties.statusData>;
-type EvapsModel = Arrays.CompactModel<PropKey,Eva.propertiesData>;
+type PropsModel = States.ArrayProxy<PropKey, Properties.statusData>;
+type EvapsModel = States.ArrayProxy<PropKey, Eva.propertiesData>;
 
 function populateModel(
   model: PropertyModel,
@@ -609,7 +666,7 @@ function populateModel(
   props.forEach((prop) => {
     const { key } = prop;
     const eva = evaps.getData(key);
-    model.setData(key,{ ...eva, ...prop });
+    model.setData(key, { ...eva, ...prop });
   });
   model.reload();
 }
@@ -618,13 +675,11 @@ export default function RenderProperties(): JSX.Element {
 
   // Hooks
   const model = React.useMemo(() => new PropertyModel(), []);
-  const props = States.useSyncArray(Properties.status);
-  const evaps = States.useSyncArray(Eva.properties);
-  const pstamp = Models.useModel(props);
-  const estamp = Models.useModel(evaps);
+  const props = States.useSyncArrayProxy(Properties.status);
+  const evaps = States.useSyncArrayProxy(Eva.properties);
   React.useEffect(() => {
-    populateModel(model,props,evaps);
-  },[model,props,evaps,pstamp,estamp]);
+    populateModel(model, props, evaps);
+  }, [model, props, evaps]);
 
   const [selection, updateSelection] = States.useSelection();
 
diff --git a/ivette/src/frama-c/kernel/SourceCode.tsx b/ivette/src/frama-c/kernel/SourceCode.tsx
index 0d143b7fa6d808b58014f22c90ca235e5e448fac..69f9cc5cdc0e1b7b07397049571d33e00b54473c 100644
--- a/ivette/src/frama-c/kernel/SourceCode.tsx
+++ b/ivette/src/frama-c/kernel/SourceCode.tsx
@@ -211,15 +211,14 @@ function useFctSource(file: string): string {
 
 // Build a callback that retrieves a location's source information.
 function useSourceGetter(): GetSource {
-  const attributes = States.useSyncArray(Ast.markerAttributes);
-  const functionsData = States.useSyncArray(Ast.functions).getArray();
+  const getAttr = States.useSyncArrayGetter(Ast.markerAttributes);
+  const functionsData = States.useSyncArrayData(Ast.functions);
   return React.useCallback(({ fct, marker }) => {
-    const markerSloc = (marker !== undefined && marker !== '') ?
-      attributes.getData(marker)?.sloc : undefined;
+    const markerSloc = getAttr(marker)?.sloc;
     const fctSloc = (fct !== undefined && fct !== '') ?
       functionsData.find((e) => e.name === fct)?.sloc : undefined;
     return markerSloc ?? fctSloc;
-  }, [attributes, functionsData]);
+  }, [getAttr, functionsData]);
 }
 
 // -----------------------------------------------------------------------------
@@ -277,7 +276,7 @@ export default function SourceCode(): JSX.Element {
 
   async function displayShortcuts(): Promise<void> {
     await Dialogs.showMessageBox({
-      buttons: [{label:"Ok"}],
+      buttons: [{ label: "Ok" }],
       details: shortcuts,
       message: 'Useful shortcuts'
     });
diff --git a/ivette/src/frama-c/kernel/api/ast/index.ts b/ivette/src/frama-c/kernel/api/ast/index.ts
index 77a01063a03366eba90da24751579561a27a0df9..c4748c158dba36d3d436d3d9b26f33489c284f56 100644
--- a/ivette/src/frama-c/kernel/api/ast/index.ts
+++ b/ivette/src/frama-c/kernel/api/ast/index.ts
@@ -147,12 +147,14 @@ export interface markerAttributesData {
   isLval: boolean;
   /** Whether it is a function symbol */
   isFunction: boolean;
+  /** Whether it is a function pointer */
+  isFunctionPointer: boolean;
   /** Whether it is a function declaration */
   isFunDecl: boolean;
   /** Function scope of the marker, if applicable */
   scope?: string;
   /** Source location */
-  sloc: source;
+  sloc?: source;
 }
 
 /** Decoder for `markerAttributesData` */
@@ -165,9 +167,10 @@ export const jMarkerAttributesData: Json.Decoder<markerAttributesData> =
     descr: Json.jString,
     isLval: Json.jBoolean,
     isFunction: Json.jBoolean,
+    isFunctionPointer: Json.jBoolean,
     isFunDecl: Json.jBoolean,
     scope: Json.jOption(Json.jString),
-    sloc: jSource,
+    sloc: Json.jOption(jSource),
   });
 
 /** Natural order for `markerAttributesData` */
@@ -175,7 +178,8 @@ export const byMarkerAttributesData: Compare.Order<markerAttributesData> =
   Compare.byFields
     <{ marker: marker, labelKind: string, titleKind: string, name: string,
        descr: string, isLval: boolean, isFunction: boolean,
-       isFunDecl: boolean, scope?: string, sloc: source }>({
+       isFunctionPointer: boolean, isFunDecl: boolean, scope?: string,
+       sloc?: source }>({
     marker: byMarker,
     labelKind: Compare.alpha,
     titleKind: Compare.alpha,
@@ -183,9 +187,10 @@ export const byMarkerAttributesData: Compare.Order<markerAttributesData> =
     descr: Compare.string,
     isLval: Compare.boolean,
     isFunction: Compare.boolean,
+    isFunctionPointer: Compare.boolean,
     isFunDecl: Compare.boolean,
     scope: Compare.defined(Compare.string),
-    sloc: bySource,
+    sloc: Compare.defined(bySource),
   });
 
 /** Signal for array [`markerAttributes`](#markerattributes)  */
@@ -240,8 +245,8 @@ export const markerAttributes: State.Array<marker,markerAttributesData> = marker
 /** Default value for `markerAttributesData` */
 export const markerAttributesDataDefault: markerAttributesData =
   { marker: markerDefault, labelKind: '', titleKind: '', name: '', descr: '',
-    isLval: false, isFunction: false, isFunDecl: false, scope: undefined,
-    sloc: sourceDefault };
+    isLval: false, isFunction: false, isFunctionPointer: false,
+    isFunDecl: false, scope: undefined, sloc: undefined };
 
 const getMainFunction_internal: Server.GetRequest<null,fct | undefined> = {
   kind: Server.RqKind.GET,
@@ -268,7 +273,7 @@ const printFunction_internal: Server.GetRequest<fct,text> = {
   name:   'kernel.ast.printFunction',
   input:  jFct,
   output: jText,
-  signals: [],
+  signals: [ { name: 'kernel.ast.changed' } ],
 };
 /** Print the AST of a function */
 export const printFunction: Server.GetRequest<fct,text>= printFunction_internal;
@@ -289,6 +294,8 @@ export interface functionsData {
   stdlib?: boolean;
   /** Is the function a Frama-C builtin? */
   builtin?: boolean;
+  /** Is the function extern? */
+  extern?: boolean;
   /** Source location */
   sloc: source;
 }
@@ -303,6 +310,7 @@ export const jFunctionsData: Json.Decoder<functionsData> =
     defined: Json.jOption(Json.jBoolean),
     stdlib: Json.jOption(Json.jBoolean),
     builtin: Json.jOption(Json.jBoolean),
+    extern: Json.jOption(Json.jBoolean),
     sloc: jSource,
   });
 
@@ -311,7 +319,7 @@ export const byFunctionsData: Compare.Order<functionsData> =
   Compare.byFields
     <{ key: Json.key<'#functions'>, name: string, signature: string,
        main?: boolean, defined?: boolean, stdlib?: boolean,
-       builtin?: boolean, sloc: source }>({
+       builtin?: boolean, extern?: boolean, sloc: source }>({
     key: Compare.string,
     name: Compare.alpha,
     signature: Compare.string,
@@ -319,6 +327,7 @@ export const byFunctionsData: Compare.Order<functionsData> =
     defined: Compare.defined(Compare.boolean),
     stdlib: Compare.defined(Compare.boolean),
     builtin: Compare.defined(Compare.boolean),
+    extern: Compare.defined(Compare.boolean),
     sloc: bySource,
   });
 
@@ -375,7 +384,7 @@ export const functions: State.Array<Json.key<'#functions'>,functionsData> = func
 export const functionsDataDefault: functionsData =
   { key: Json.jKey<'#functions'>('#functions')(''), name: '', signature: '',
     main: undefined, defined: undefined, stdlib: undefined,
-    builtin: undefined, sloc: sourceDefault };
+    builtin: undefined, extern: undefined, sloc: sourceDefault };
 
 /** Updated AST information */
 export const getInformationUpdate: Server.Signal = {
diff --git a/ivette/src/frama-c/kernel/style.css b/ivette/src/frama-c/kernel/style.css
index 6a7da3a4b4270b277a699419ba5c908199d278a2..d0bb884d976534c1b7e815186ad50d8c66f3d603 100644
--- a/ivette/src/frama-c/kernel/style.css
+++ b/ivette/src/frama-c/kernel/style.css
@@ -56,6 +56,14 @@
 /* --- Globals                                                            --- */
 /* -------------------------------------------------------------------------- */
 
+.globals-info {
+    color: var(--info-text-discrete);
+    font-style: italic;
+    padding-left: 20px;
+    padding-right: 10px;
+    display: block;
+}
+
 .globals-main label {
     text-decoration: underline;
 }
diff --git a/ivette/src/frama-c/plugins/callgraph/api/index.ts b/ivette/src/frama-c/plugins/callgraph/api/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e231a66fbbae3bb315cd9a85a06f47096f0311db
--- /dev/null
+++ b/ivette/src/frama-c/plugins/callgraph/api/index.ts
@@ -0,0 +1,217 @@
+/* ************************************************************************ */
+/*                                                                          */
+/*   This file is part of Frama-C.                                          */
+/*                                                                          */
+/*   Copyright (C) 2007-2023                                                */
+/*     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).             */
+/*                                                                          */
+/* ************************************************************************ */
+
+/* --- Generated Frama-C Server API --- */
+
+/**
+   Callgraph
+   @packageDocumentation
+   @module frama-c/plugins/callgraph/api
+*/
+
+//@ts-ignore
+import * as Json from 'dome/data/json';
+//@ts-ignore
+import * as Compare from 'dome/data/compare';
+//@ts-ignore
+import * as Server from 'frama-c/server';
+//@ts-ignore
+import * as State from 'frama-c/states';
+
+//@ts-ignore
+import { byFct } from 'frama-c/kernel/api/ast';
+//@ts-ignore
+import { fct } from 'frama-c/kernel/api/ast';
+//@ts-ignore
+import { fctDefault } from 'frama-c/kernel/api/ast';
+//@ts-ignore
+import { jFct } from 'frama-c/kernel/api/ast';
+//@ts-ignore
+import { byTag } from 'frama-c/kernel/api/data';
+//@ts-ignore
+import { jTag } from 'frama-c/kernel/api/data';
+//@ts-ignore
+import { tag } from 'frama-c/kernel/api/data';
+//@ts-ignore
+import { tagDefault } from 'frama-c/kernel/api/data';
+
+export interface vertex {
+  /** The function represented by the node */
+  kf: fct;
+  /** whether this node is the root of a service */
+  is_root: boolean;
+  /** the root of this node's service */
+  root: fct;
+}
+
+/** Decoder for `vertex` */
+export const jVertex: Json.Decoder<vertex> =
+  Json.jObject({ kf: jFct, is_root: Json.jBoolean, root: jFct,});
+
+/** Natural order for `vertex` */
+export const byVertex: Compare.Order<vertex> =
+  Compare.byFields
+    <{ kf: fct, is_root: boolean, root: fct }>({
+    kf: byFct,
+    is_root: Compare.boolean,
+    root: byFct,
+  });
+
+/** Default value for `vertex` */
+export const vertexDefault: vertex =
+  { kf: fctDefault, is_root: false, root: fctDefault };
+
+/** Whether the call goes through services or not */
+export enum edgeKind {
+  /** a call between two services */
+  inter_services = 'inter_services',
+  /** a call inside a service */
+  inter_functions = 'inter_functions',
+  /** both cases above */
+  both = 'both',
+}
+
+/** Decoder for `edgeKind` */
+export const jEdgeKind: Json.Decoder<edgeKind> = Json.jEnum(edgeKind);
+
+/** Natural order for `edgeKind` */
+export const byEdgeKind: Compare.Order<edgeKind> = Compare.byEnum(edgeKind);
+
+/** Default value for `edgeKind` */
+export const edgeKindDefault: edgeKind = edgeKind.inter_services;
+
+const edgeKindTags_internal: Server.GetRequest<null,tag[]> = {
+  kind: Server.RqKind.GET,
+  name:   'plugins.callgraph.edgeKindTags',
+  input:  Json.jNull,
+  output: Json.jArray(jTag),
+  signals: [],
+};
+/** Registered tags for the above type. */
+export const edgeKindTags: Server.GetRequest<null,tag[]>= edgeKindTags_internal;
+
+export interface edge {
+  /** src */
+  src: fct;
+  /** dst */
+  dst: fct;
+  /** kind */
+  kind: edgeKind;
+}
+
+/** Decoder for `edge` */
+export const jEdge: Json.Decoder<edge> =
+  Json.jObject({ src: jFct, dst: jFct, kind: jEdgeKind,});
+
+/** Natural order for `edge` */
+export const byEdge: Compare.Order<edge> =
+  Compare.byFields
+    <{ src: fct, dst: fct, kind: edgeKind }>({
+    src: byFct,
+    dst: byFct,
+    kind: byEdgeKind,
+  });
+
+/** Default value for `edge` */
+export const edgeDefault: edge =
+  { src: fctDefault, dst: fctDefault, kind: edgeKindDefault };
+
+/** The callgraph of the current project */
+export interface graph {
+  /** vertices */
+  vertices: vertex[];
+  /** edges */
+  edges: edge[];
+}
+
+/** Decoder for `graph` */
+export const jGraph: Json.Decoder<graph> =
+  Json.jObject({ vertices: Json.jArray(jVertex), edges: Json.jArray(jEdge),});
+
+/** Natural order for `graph` */
+export const byGraph: Compare.Order<graph> =
+  Compare.byFields
+    <{ vertices: vertex[], edges: edge[] }>({
+    vertices: Compare.array(byVertex),
+    edges: Compare.array(byEdge),
+  });
+
+/** Default value for `graph` */
+export const graphDefault: graph = { vertices: [], edges: [] };
+
+/** Signal for state [`callgraph`](#callgraph)  */
+export const signalCallgraph: Server.Signal = {
+  name: 'plugins.callgraph.signalCallgraph',
+};
+
+const getCallgraph_internal: Server.GetRequest<null,graph | undefined> = {
+  kind: Server.RqKind.GET,
+  name:   'plugins.callgraph.getCallgraph',
+  input:  Json.jNull,
+  output: Json.jOption(jGraph),
+  signals: [],
+};
+/** Getter for state [`callgraph`](#callgraph)  */
+export const getCallgraph: Server.GetRequest<null,graph | undefined>= getCallgraph_internal;
+
+const callgraph_internal: State.Value<graph | undefined> = {
+  name: 'plugins.callgraph.callgraph',
+  signal: signalCallgraph,
+  getter: getCallgraph,
+};
+/** The current callgraph or an empty graph if it has not been computed yet */
+export const callgraph: State.Value<graph | undefined> = callgraph_internal;
+
+/** Signal for state [`isComputed`](#iscomputed)  */
+export const signalIsComputed: Server.Signal = {
+  name: 'plugins.callgraph.signalIsComputed',
+};
+
+const getIsComputed_internal: Server.GetRequest<null,boolean> = {
+  kind: Server.RqKind.GET,
+  name:   'plugins.callgraph.getIsComputed',
+  input:  Json.jNull,
+  output: Json.jBoolean,
+  signals: [],
+};
+/** Getter for state [`isComputed`](#iscomputed)  */
+export const getIsComputed: Server.GetRequest<null,boolean>= getIsComputed_internal;
+
+const isComputed_internal: State.Value<boolean> = {
+  name: 'plugins.callgraph.isComputed',
+  signal: signalIsComputed,
+  getter: getIsComputed,
+};
+/** This boolean is true if the graph has been computed */
+export const isComputed: State.Value<boolean> = isComputed_internal;
+
+const compute_internal: Server.ExecRequest<null,null> = {
+  kind: Server.RqKind.EXEC,
+  name:   'plugins.callgraph.compute',
+  input:  Json.jNull,
+  output: Json.jNull,
+  signals: [],
+};
+/** Compute the callgraph for the current project */
+export const compute: Server.ExecRequest<null,null>= compute_internal;
+
+/* ------------------------------------- */
diff --git a/ivette/src/frama-c/plugins/callgraph/callgraph.css b/ivette/src/frama-c/plugins/callgraph/callgraph.css
new file mode 100644
index 0000000000000000000000000000000000000000..4360e1461c2db03e11e4e3d205ce09e17ea74809
--- /dev/null
+++ b/ivette/src/frama-c/plugins/callgraph/callgraph.css
@@ -0,0 +1,6 @@
+.callgraph-computing {
+  max-width: 90%;
+  max-height: 200px;
+  fill: var(--info-text-discrete);
+  margin: auto;
+}
diff --git a/ivette/src/frama-c/plugins/callgraph/graph-style.json b/ivette/src/frama-c/plugins/callgraph/graph-style.json
new file mode 100644
index 0000000000000000000000000000000000000000..e1aff869e939ed8a04bbc64618ede99ce4e19db3
--- /dev/null
+++ b/ivette/src/frama-c/plugins/callgraph/graph-style.json
@@ -0,0 +1,42 @@
+[
+  {
+    "selector": "node",
+    "style": {
+      "shape": "round-rectangle",
+      "background-color": "#666",
+      "label": "data(id)",
+      "color": "white",
+      "text-outline-width": 2,
+      "text-outline-color": "#666",
+      "text-valign" : "center",
+      "padding" : "6px",
+      "border-width": 1,
+      "text-wrap" : "wrap"
+    }
+  },
+  {
+    "selector": "node[?is_root]",
+    "style": {
+      "border-width": "2px"
+    }
+  },
+  {
+    "selector": "edge",
+    "style": {
+      "width": 2,
+      "line-color": "#888",
+      "curve-style": "bezier",
+      "target-arrow-shape": "vee",
+      "target-arrow-color": "#888",
+      "arrow-scale": 2.0
+    }
+  },
+  {
+    "selector": ".callstack-selected",
+    "style": {
+      "overlay-color": "#8bf",
+      "overlay-padding": "8px",
+      "overlay-opacity": 0.4
+    }
+  }
+]
diff --git a/ivette/src/frama-c/plugins/callgraph/index.tsx b/ivette/src/frama-c/plugins/callgraph/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..e0b1861ef05335fefc5bed6d61b246789f732162
--- /dev/null
+++ b/ivette/src/frama-c/plugins/callgraph/index.tsx
@@ -0,0 +1,210 @@
+/* ************************************************************************ */
+/*                                                                          */
+/*   This file is part of Frama-C.                                          */
+/*                                                                          */
+/*   Copyright (C) 2007-2023                                                */
+/*     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).             */
+/*                                                                          */
+/* ************************************************************************ */
+
+import React, { useEffect, useState } from 'react';
+import _ from 'lodash';
+import * as Ivette from 'ivette';
+import * as Server from 'frama-c/server';
+
+import * as AstAPI from 'frama-c/kernel/api/ast';
+import * as CgAPI from './api';
+import * as ValuesAPI from 'frama-c/plugins/eva/api/values';
+
+import Cy from 'cytoscape';
+import CytoscapeComponent from 'react-cytoscapejs';
+import 'frama-c/plugins/dive/cytoscape_libs';
+import 'cytoscape-panzoom/cytoscape.js-panzoom.css';
+import style from './graph-style.json';
+
+import { useGlobalState } from 'dome/data/states';
+import { useRequest, useSelection, useSyncValue } from 'frama-c/states';
+
+import gearsIcon from 'frama-c/plugins/eva/images/gears.svg';
+import { CallstackState } from 'frama-c/plugins/eva/valuetable';
+
+import './callgraph.css';
+
+
+// --------------------------------------------------------------------------
+// --- Nodes label measurement
+// --------------------------------------------------------------------------
+
+/* eslint-disable @typescript-eslint/no-explicit-any */
+function getWidth(node: any): string {
+  const padding = 10;
+  const min = 50;
+  const canvas = document.querySelector('canvas[data-id="layer2-node"]');
+  if (canvas instanceof HTMLCanvasElement) {
+    const context = canvas.getContext('2d');
+    if (context) {
+      const fStyle = node.pstyle('font-style').strValue;
+      const weight = node.pstyle('font-weight').strValue;
+      const size = node.pstyle('font-size').pfValue;
+      const family = node.pstyle('font-family').strValue;
+      context.font = `${fStyle} ${weight} ${size}px ${family}`;
+      const width = context.measureText(node.data('id')).width;
+      return `${Math.max(min, width + padding)}px`;
+    }
+  }
+  return `${min}px`;
+}
+/* eslint-enable @typescript-eslint/no-explicit-any */
+
+(style as unknown[]).push({
+    selector: 'node',
+    style: { width: getWidth }
+  });
+
+
+// --------------------------------------------------------------------------
+// --- Graph
+// --------------------------------------------------------------------------
+
+function edgeId(source: AstAPI.fct, target: AstAPI.fct): string {
+  return `${source}-${target}`;
+}
+
+function convertGraph(graph: CgAPI.graph): object[] {
+  const elements = [];
+  for (const v of graph.vertices) {
+    elements.push({ data: { ...v, id: v.kf } });
+  }
+  for (const e of graph.edges) {
+    const id = edgeId(e.src, e.dst);
+    elements.push({ data: { ...e, id, source: e.src, target: e.dst } });
+  }
+  return elements;
+}
+
+type callstack = {
+  callee: AstAPI.fct,
+  caller?: AstAPI.fct,
+  stmt?: AstAPI.marker,
+  rank?: number
+}[]
+
+function selectFct(cy: Cy.Core, fct: string | undefined): void {
+  const className = 'marker-selected';
+  cy.$(`.${className}`).removeClass(className);
+  if (fct) {
+    cy.$(`node[id='${fct}']`).addClass(className);
+  }
+}
+
+function selectCallstack(cy: Cy.Core, callstack: callstack | undefined): void {
+  const className = 'callstack-selected';
+  cy.$(`.${className}`).removeClass(className);
+  callstack?.forEach((call) => {
+    cy.$(`node[id='${call.callee}']`).addClass(className);
+    if (call.caller) {
+      const id = edgeId(call.caller, call.callee);
+      cy.$(`edge[id='${id}']`).addClass(className);
+    }
+  });
+}
+
+function Callgraph() : JSX.Element {
+  const isComputed = useSyncValue(CgAPI.isComputed);
+  const graph = useSyncValue(CgAPI.callgraph);
+  const [cy, setCy] = useState<Cy.Core>();
+  const [cs] = useGlobalState(CallstackState);
+  const [selection, setSelection] = useSelection();
+  const callstack = useRequest(ValuesAPI.getCallstackInfo, cs);
+
+  const layout = { name: 'cola', nodeSpacing: 32 };
+  const computedStyle = getComputedStyle(document.documentElement);
+  const styleVariables =
+    { ['code-select']: computedStyle.getPropertyValue("--code-select") };
+
+  const completeStyle = [
+    ...style,
+    {
+      "selector": ".marker-selected",
+      "style": { "background-color": styleVariables['code-select'] }
+    }
+  ];
+
+  // Marker selection
+  useEffect(() => {
+    cy && selectFct(cy, selection.current?.fct);
+  }, [cy, selection]);
+
+  // Callstack selection
+  useEffect(() => {
+    cy && selectCallstack(cy, callstack);
+  }, [cy, callstack]);
+
+  // Click on graph
+  useEffect(() => {
+    if (cy) {
+      cy.off('click');
+      cy.on('click', 'node', (event) => {
+        const fct = event.target.id() as string;
+        setSelection({ location: { fct } });
+      });
+    }
+  }, [cy, setSelection]);
+
+
+  if (isComputed === false) {
+    Server.send(CgAPI.compute, null);
+    return (<img src={gearsIcon} className="callgraph-computing" />);
+  }
+  else if (graph !== undefined) {
+    return (
+      <CytoscapeComponent
+        elements={convertGraph(graph)}
+        stylesheet={completeStyle}
+        cy={setCy}
+        layout={layout}
+        style={{ width: '100%', height: '100%' }}
+      />);
+  }
+  else {
+    return (<></>);
+  }
+}
+
+
+// --------------------------------------------------------------------------
+// --- Ivette Component
+// --------------------------------------------------------------------------
+
+function CallgraphComponent(): JSX.Element {
+  // Component
+  return (
+    <>
+      <Callgraph />
+    </>
+  );
+}
+
+
+Ivette.registerComponent({
+  id: 'frama-c.plugins.callgraph',
+  label: 'Call Graph',
+  group: 'frama-c.plugins',
+  rank: 3,
+  title:
+    'Display a graph showing calls between functions.',
+  children: <CallgraphComponent />,
+});
diff --git a/ivette/src/frama-c/plugins/callgraph/pkg.json b/ivette/src/frama-c/plugins/callgraph/pkg.json
new file mode 100644
index 0000000000000000000000000000000000000000..01be594c9eea276d40d1967201e4675ea3cdc1f8
--- /dev/null
+++ b/ivette/src/frama-c/plugins/callgraph/pkg.json
@@ -0,0 +1,3 @@
+{
+  "name": "Frama-C/Callgraph"
+}
diff --git a/ivette/src/frama-c/plugins/dive/api/index.ts b/ivette/src/frama-c/plugins/dive/api/index.ts
index cd47a1579e051faaecd79ad5c1b95b0f7f8bed4f..62dc2171f78d04ff87fbd13ac76c68a9aa6631a3 100644
--- a/ivette/src/frama-c/plugins/dive/api/index.ts
+++ b/ivette/src/frama-c/plugins/dive/api/index.ts
@@ -53,6 +53,14 @@ import { locationDefault } from 'frama-c/kernel/api/ast';
 import { marker } from 'frama-c/kernel/api/ast';
 //@ts-ignore
 import { markerDefault } from 'frama-c/kernel/api/ast';
+//@ts-ignore
+import { byTag } from 'frama-c/kernel/api/data';
+//@ts-ignore
+import { jTag } from 'frama-c/kernel/api/data';
+//@ts-ignore
+import { tag } from 'frama-c/kernel/api/data';
+//@ts-ignore
+import { tagDefault } from 'frama-c/kernel/api/data';
 
 /** Parametrization of the exploration range. */
 export interface range {
@@ -117,20 +125,21 @@ export const byNodeId: Compare.Order<nodeId> = Compare.number;
 /** Default value for `nodeId` */
 export const nodeIdDefault: nodeId = 0;
 
-/** A callsite */
-export type callsite = { fun: string, instr: number | string };
+/** callsite */
+export type callsite = { fun: string, instr: number | "global" };
 
 /** Decoder for `callsite` */
 export const jCallsite: Json.Decoder<callsite> =
   Json.jObject({
     fun: Json.jString,
-    instr: Json.jUnion<number | string>( Json.jNumber, Json.jString,),
+    instr: Json.jUnion<number | "global">( Json.jNumber, Json.jTag("global"),
+           ),
   });
 
 /** Natural order for `callsite` */
 export const byCallsite: Compare.Order<callsite> =
   Compare.byFields
-    <{ fun: string, instr: number | string }>({
+    <{ fun: string, instr: number | "global" }>({
     fun: Compare.string,
     instr: Compare.structural,
   });
@@ -152,7 +161,12 @@ export const byCallstack: Compare.Order<callstack> =
 export const callstackDefault: callstack = [];
 
 /** The description of a node locality */
-export type nodeLocality = { file: string, callstack?: callstack };
+export interface nodeLocality {
+  /** file */
+  file: string;
+  /** callstack */
+  callstack?: callstack;
+}
 
 /** Decoder for `nodeLocality` */
 export const jNodeLocality: Json.Decoder<nodeLocality> =
@@ -170,65 +184,238 @@ export const byNodeLocality: Compare.Order<nodeLocality> =
 export const nodeLocalityDefault: nodeLocality =
   { file: '', callstack: undefined };
 
-/** A graph node */
-export type node =
-  { id: nodeId, label: string, kind: string, locality: nodeLocality,
-    is_root: boolean, backward_explored: string, forward_explored: string,
-    writes: location[], values?: string, range: number | string,
-    type?: string, taint?: "direct" | "indirect" | "untainted" };
+/** The nature of a node */
+export enum nodeKind {
+  /** a single memory cell */
+  scalar = 'scalar',
+  /** a memory bloc containing cells */
+  composite = 'composite',
+  /** a set of memory locations designated by an lvalue */
+  scattered = 'scattered',
+  /** an unresolved memory location */
+  unknown = 'unknown',
+  /** an alarm emitted by Frama-C */
+  alarm = 'alarm',
+  /** a memory location designated by a range of adresses */
+  absolute = 'absolute',
+  /** a string literal */
+  string = 'string',
+  /** a placeholder node when an error prevented the generation process */
+  error = 'error',
+  /** a numeric constant literal */
+  const = 'const',
+}
+
+/** Decoder for `nodeKind` */
+export const jNodeKind: Json.Decoder<nodeKind> = Json.jEnum(nodeKind);
+
+/** Natural order for `nodeKind` */
+export const byNodeKind: Compare.Order<nodeKind> = Compare.byEnum(nodeKind);
+
+/** Default value for `nodeKind` */
+export const nodeKindDefault: nodeKind = nodeKind.scalar;
+
+const nodeKindTags_internal: Server.GetRequest<null,tag[]> = {
+  kind: Server.RqKind.GET,
+  name:   'plugins.dive.nodeKindTags',
+  input:  Json.jNull,
+  output: Json.jArray(jTag),
+  signals: [],
+};
+/** Registered tags for the above type. */
+export const nodeKindTags: Server.GetRequest<null,tag[]>= nodeKindTags_internal;
+
+/** Taint of a memory location */
+export enum taint {
+  /** not tainted by anything */
+  untainted = 'untainted',
+  /** tainted by control */
+  indirect = 'indirect',
+  /** tainted by data */
+  direct = 'direct',
+}
+
+/** Decoder for `taint` */
+export const jTaint: Json.Decoder<taint> = Json.jEnum(taint);
+
+/** Natural order for `taint` */
+export const byTaint: Compare.Order<taint> = Compare.byEnum(taint);
+
+/** Default value for `taint` */
+export const taintDefault: taint = taint.untainted;
+
+const taintTags_internal: Server.GetRequest<null,tag[]> = {
+  kind: Server.RqKind.GET,
+  name:   'plugins.dive.taintTags',
+  input:  Json.jNull,
+  output: Json.jArray(jTag),
+  signals: [],
+};
+/** Registered tags for the above type. */
+export const taintTags: Server.GetRequest<null,tag[]>= taintTags_internal;
+
+/** The computation state of a node read or write dependencies */
+export enum exploration {
+  /** all dependencies have been computed */
+  yes = 'yes',
+  /** some dependencies have been explored */
+  partial = 'partial',
+  /** dependencies have not been computed */
+  no = 'no',
+}
+
+/** Decoder for `exploration` */
+export const jExploration: Json.Decoder<exploration> =
+  Json.jEnum(exploration);
+
+/** Natural order for `exploration` */
+export const byExploration: Compare.Order<exploration> =
+  Compare.byEnum(exploration);
+
+/** Default value for `exploration` */
+export const explorationDefault: exploration = exploration.yes;
+
+const explorationTags_internal: Server.GetRequest<null,tag[]> = {
+  kind: Server.RqKind.GET,
+  name:   'plugins.dive.explorationTags',
+  input:  Json.jNull,
+  output: Json.jArray(jTag),
+  signals: [],
+};
+/** Registered tags for the above type. */
+export const explorationTags: Server.GetRequest<null,tag[]>= explorationTags_internal;
+
+/** A qualitative description of the range of values that this node can take. */
+export enum nodeSpecialRange {
+  /** no value ever computed for this node */
+  empty = 'empty',
+  /** this node can only have one value */
+  singleton = 'singleton',
+  /** this node can take almost all values of its type */
+  wide = 'wide',
+}
+
+/** Decoder for `nodeSpecialRange` */
+export const jNodeSpecialRange: Json.Decoder<nodeSpecialRange> =
+  Json.jEnum(nodeSpecialRange);
+
+/** Natural order for `nodeSpecialRange` */
+export const byNodeSpecialRange: Compare.Order<nodeSpecialRange> =
+  Compare.byEnum(nodeSpecialRange);
+
+/** Default value for `nodeSpecialRange` */
+export const nodeSpecialRangeDefault: nodeSpecialRange =
+  nodeSpecialRange.empty;
+
+const nodeSpecialRangeTags_internal: Server.GetRequest<null,tag[]> = {
+  kind: Server.RqKind.GET,
+  name:   'plugins.dive.nodeSpecialRangeTags',
+  input:  Json.jNull,
+  output: Json.jArray(jTag),
+  signals: [],
+};
+/** Registered tags for the above type. */
+export const nodeSpecialRangeTags: Server.GetRequest<null,tag[]>= nodeSpecialRangeTags_internal;
+
+/** A qualitative or quantitative description of the range of values that this node can take. */
+export type nodeRange = number | nodeSpecialRange;
+
+/** Decoder for `nodeRange` */
+export const jNodeRange: Json.Decoder<nodeRange> =
+  Json.jUnion<number | nodeSpecialRange>( Json.jNumber, jNodeSpecialRange,);
+
+/** Natural order for `nodeRange` */
+export const byNodeRange: Compare.Order<nodeRange> = Compare.structural;
+
+/** Default value for `nodeRange` */
+export const nodeRangeDefault: nodeRange = 0;
+
+export interface node {
+  /** id */
+  id: nodeId;
+  /** label */
+  label: string;
+  /** nkind */
+  nkind: nodeKind;
+  /** locality */
+  locality: nodeLocality;
+  /** is_root */
+  is_root: boolean;
+  /** backward_explored */
+  backward_explored: exploration;
+  /** forward_explored */
+  forward_explored: exploration;
+  /** writes */
+  writes: location[];
+  /** values */
+  values?: string;
+  /** range */
+  range: nodeRange;
+  /** type */
+  type?: string;
+  /** taint */
+  taint?: taint;
+}
 
 /** Decoder for `node` */
 export const jNode: Json.Decoder<node> =
   Json.jObject({
     id: jNodeId,
     label: Json.jString,
-    kind: Json.jString,
+    nkind: jNodeKind,
     locality: jNodeLocality,
     is_root: Json.jBoolean,
-    backward_explored: Json.jString,
-    forward_explored: Json.jString,
+    backward_explored: jExploration,
+    forward_explored: jExploration,
     writes: Json.jArray(jLocation),
     values: Json.jOption(Json.jString),
-    range: Json.jUnion<number | string>( Json.jNumber, Json.jString,),
+    range: jNodeRange,
     type: Json.jOption(Json.jString),
-    taint: Json.jOption(
-             Json.jUnion<"direct" | "indirect" | "untainted">(
-               Json.jTag("direct"),
-               Json.jTag("indirect"),
-               Json.jTag("untainted"),
-             )),
+    taint: Json.jOption(jTaint),
   });
 
 /** Natural order for `node` */
 export const byNode: Compare.Order<node> =
   Compare.byFields
-    <{ id: nodeId, label: string, kind: string, locality: nodeLocality,
-       is_root: boolean, backward_explored: string, forward_explored: string,
-       writes: location[], values?: string, range: number | string,
-       type?: string, taint?: "direct" | "indirect" | "untainted" }>({
+    <{ id: nodeId, label: string, nkind: nodeKind, locality: nodeLocality,
+       is_root: boolean, backward_explored: exploration,
+       forward_explored: exploration, writes: location[], values?: string,
+       range: nodeRange, type?: string, taint?: taint }>({
     id: byNodeId,
     label: Compare.string,
-    kind: Compare.string,
+    nkind: byNodeKind,
     locality: byNodeLocality,
     is_root: Compare.boolean,
-    backward_explored: Compare.string,
-    forward_explored: Compare.string,
+    backward_explored: byExploration,
+    forward_explored: byExploration,
     writes: Compare.array(byLocation),
     values: Compare.defined(Compare.string),
-    range: Compare.structural,
+    range: byNodeRange,
     type: Compare.defined(Compare.string),
-    taint: Compare.defined(Compare.structural),
+    taint: Compare.defined(byTaint),
   });
 
 /** Default value for `node` */
 export const nodeDefault: node =
-  { id: nodeIdDefault, label: '', kind: '', locality: nodeLocalityDefault,
-    is_root: false, backward_explored: '', forward_explored: '', writes: [],
-    values: undefined, range: 0, type: undefined, taint: undefined };
+  { id: nodeIdDefault, label: '', nkind: nodeKindDefault,
+    locality: nodeLocalityDefault, is_root: false,
+    backward_explored: explorationDefault,
+    forward_explored: explorationDefault, writes: [], values: undefined,
+    range: nodeRangeDefault, type: undefined, taint: undefined };
 
 /** The dependency between two nodes */
-export type dependency =
-  { id: number, src: nodeId, dst: nodeId, kind: string, origins: location[] };
+export interface dependency {
+  /** id */
+  id: number;
+  /** src */
+  src: nodeId;
+  /** dst */
+  dst: nodeId;
+  /** dkind */
+  dkind: string;
+  /** origins */
+  origins: location[];
+}
 
 /** Decoder for `dependency` */
 export const jDependency: Json.Decoder<dependency> =
@@ -236,77 +423,111 @@ export const jDependency: Json.Decoder<dependency> =
     id: Json.jNumber,
     src: jNodeId,
     dst: jNodeId,
-    kind: Json.jString,
+    dkind: Json.jString,
     origins: Json.jArray(jLocation),
   });
 
 /** Natural order for `dependency` */
 export const byDependency: Compare.Order<dependency> =
   Compare.byFields
-    <{ id: number, src: nodeId, dst: nodeId, kind: string,
+    <{ id: number, src: nodeId, dst: nodeId, dkind: string,
        origins: location[] }>({
     id: Compare.number,
     src: byNodeId,
     dst: byNodeId,
-    kind: Compare.string,
+    dkind: Compare.string,
     origins: Compare.array(byLocation),
   });
 
 /** Default value for `dependency` */
 export const dependencyDefault: dependency =
-  { id: 0, src: nodeIdDefault, dst: nodeIdDefault, kind: '', origins: [] };
+  { id: 0, src: nodeIdDefault, dst: nodeIdDefault, dkind: '', origins: [] };
+
+/** A graph element, either a node or a dependency */
+export type element = node | dependency;
+
+/** Decoder for `element` */
+export const jElement: Json.Decoder<element> =
+  Json.jUnion<node | dependency>( jNode, jDependency,);
 
-/** The whole graph being built */
-export type graphData = { nodes: node[], deps: dependency[] };
+/** Natural order for `element` */
+export const byElement: Compare.Order<element> = Compare.structural;
+
+/** Default value for `element` */
+export const elementDefault: element = nodeDefault;
+
+/** Data for array rows [`graph`](#graph)  */
+export interface graphData {
+  /** Entry identifier. */
+  key: Json.key<'#graph'>;
+  /** a graph element */
+  element: element;
+}
 
 /** Decoder for `graphData` */
 export const jGraphData: Json.Decoder<graphData> =
-  Json.jObject({ nodes: Json.jArray(jNode), deps: Json.jArray(jDependency),});
+  Json.jObject({ key: Json.jKey<'#graph'>('#graph'), element: jElement,});
 
 /** Natural order for `graphData` */
 export const byGraphData: Compare.Order<graphData> =
   Compare.byFields
-    <{ nodes: node[], deps: dependency[] }>({
-    nodes: Compare.array(byNode),
-    deps: Compare.array(byDependency),
+    <{ key: Json.key<'#graph'>, element: element }>({
+    key: Compare.string,
+    element: byElement,
   });
 
-/** Default value for `graphData` */
-export const graphDataDefault: graphData = { nodes: [], deps: [] };
-
-/** Graph differences from the last action. */
-export type diffData =
-  { root?: nodeId, add: { nodes: node[], deps: dependency[] }, sub: nodeId[]
-    };
-
-/** Decoder for `diffData` */
-export const jDiffData: Json.Decoder<diffData> =
-  Json.jObject({
-    root: Json.jOption(jNodeId),
-    add: Json.jObject({
-           nodes: Json.jArray(jNode),
-           deps: Json.jArray(jDependency),
-         }),
-    sub: Json.jArray(jNodeId),
-  });
+/** Signal for array [`graph`](#graph)  */
+export const signalGraph: Server.Signal = {
+  name: 'plugins.dive.signalGraph',
+};
 
-/** Natural order for `diffData` */
-export const byDiffData: Compare.Order<diffData> =
-  Compare.byFields
-    <{ root?: nodeId, add: { nodes: node[], deps: dependency[] },
-       sub: nodeId[] }>({
-    root: Compare.defined(byNodeId),
-    add: Compare.byFields
-           <{ nodes: node[], deps: dependency[] }>({
-           nodes: Compare.array(byNode),
-           deps: Compare.array(byDependency),
-         }),
-    sub: Compare.array(byNodeId),
-  });
+const reloadGraph_internal: Server.GetRequest<null,null> = {
+  kind: Server.RqKind.GET,
+  name:   'plugins.dive.reloadGraph',
+  input:  Json.jNull,
+  output: Json.jNull,
+  signals: [],
+};
+/** Force full reload for array [`graph`](#graph)  */
+export const reloadGraph: Server.GetRequest<null,null>= reloadGraph_internal;
+
+const fetchGraph_internal: Server.GetRequest<
+  number,
+  { reload: boolean, removed: Json.key<'#graph'>[], updated: graphData[],
+    pending: number }
+  > = {
+  kind: Server.RqKind.GET,
+  name:   'plugins.dive.fetchGraph',
+  input:  Json.jNumber,
+  output: Json.jObject({
+            reload: Json.jBoolean,
+            removed: Json.jArray(Json.jKey<'#graph'>('#graph')),
+            updated: Json.jArray(jGraphData),
+            pending: Json.jNumber,
+          }),
+  signals: [],
+};
+/** Data fetcher for array [`graph`](#graph)  */
+export const fetchGraph: Server.GetRequest<
+  number,
+  { reload: boolean, removed: Json.key<'#graph'>[], updated: graphData[],
+    pending: number }
+  >= fetchGraph_internal;
+
+const graph_internal: State.Array<Json.key<'#graph'>,graphData> = {
+  name: 'plugins.dive.graph',
+  getkey: ((d:graphData) => d.key),
+  signal: signalGraph,
+  fetch: fetchGraph,
+  reload: reloadGraph,
+  order: byGraphData,
+};
+/** The graph being built as a set of vertices and edges */
+export const graph: State.Array<Json.key<'#graph'>,graphData> = graph_internal;
 
-/** Default value for `diffData` */
-export const diffDataDefault: diffData =
-  { root: undefined, add: { nodes: [], deps: [] }, sub: [] };
+/** Default value for `graphData` */
+export const graphDataDefault: graphData =
+  { key: Json.jKey<'#graph'>('#graph')(''), element: elementDefault };
 
 const window_internal: Server.SetRequest<explorationWindow,null> = {
   kind: Server.RqKind.SET,
@@ -318,16 +539,6 @@ const window_internal: Server.SetRequest<explorationWindow,null> = {
 /** Set the exploration window */
 export const window: Server.SetRequest<explorationWindow,null>= window_internal;
 
-const graph_internal: Server.GetRequest<null,graphData> = {
-  kind: Server.RqKind.GET,
-  name:   'plugins.dive.graph',
-  input:  Json.jNull,
-  output: jGraphData,
-  signals: [],
-};
-/** Retrieve the whole graph */
-export const graph: Server.GetRequest<null,graphData>= graph_internal;
-
 const clear_internal: Server.ExecRequest<null,null> = {
   kind: Server.RqKind.EXEC,
   name:   'plugins.dive.clear',
@@ -338,44 +549,44 @@ const clear_internal: Server.ExecRequest<null,null> = {
 /** Erase the graph and start over with an empty one */
 export const clear: Server.ExecRequest<null,null>= clear_internal;
 
-const add_internal: Server.ExecRequest<marker,diffData> = {
+const add_internal: Server.ExecRequest<marker,nodeId | undefined> = {
   kind: Server.RqKind.EXEC,
   name:   'plugins.dive.add',
   input:  jMarker,
-  output: jDiffData,
+  output: Json.jOption(jNodeId),
   signals: [],
 };
 /** Add a node to the graph */
-export const add: Server.ExecRequest<marker,diffData>= add_internal;
+export const add: Server.ExecRequest<marker,nodeId | undefined>= add_internal;
 
-const explore_internal: Server.ExecRequest<nodeId,diffData> = {
+const explore_internal: Server.ExecRequest<nodeId,null> = {
   kind: Server.RqKind.EXEC,
   name:   'plugins.dive.explore',
   input:  jNodeId,
-  output: jDiffData,
+  output: Json.jNull,
   signals: [],
 };
 /** Explore the graph starting from an existing vertex */
-export const explore: Server.ExecRequest<nodeId,diffData>= explore_internal;
+export const explore: Server.ExecRequest<nodeId,null>= explore_internal;
 
-const show_internal: Server.ExecRequest<nodeId,diffData> = {
+const show_internal: Server.ExecRequest<nodeId,null> = {
   kind: Server.RqKind.EXEC,
   name:   'plugins.dive.show',
   input:  jNodeId,
-  output: jDiffData,
+  output: Json.jNull,
   signals: [],
 };
 /** Show the dependencies of an existing vertex */
-export const show: Server.ExecRequest<nodeId,diffData>= show_internal;
+export const show: Server.ExecRequest<nodeId,null>= show_internal;
 
-const hide_internal: Server.ExecRequest<nodeId,diffData> = {
+const hide_internal: Server.ExecRequest<nodeId,null> = {
   kind: Server.RqKind.EXEC,
   name:   'plugins.dive.hide',
   input:  jNodeId,
-  output: jDiffData,
+  output: Json.jNull,
   signals: [],
 };
 /** Hide the dependencies of an existing vertex */
-export const hide: Server.ExecRequest<nodeId,diffData>= hide_internal;
+export const hide: Server.ExecRequest<nodeId,null>= hide_internal;
 
 /* ------------------------------------- */
diff --git a/ivette/src/frama-c/plugins/dive/index.tsx b/ivette/src/frama-c/plugins/dive/index.tsx
index ea93fa70f1497e6ae20e69dc94264318f3db3f1f..77dd2a9f9aa1316c467648d7493450d287645c96 100644
--- a/ivette/src/frama-c/plugins/dive/index.tsx
+++ b/ivette/src/frama-c/plugins/dive/index.tsx
@@ -28,7 +28,7 @@ import * as Ivette from 'ivette';
 import * as Server from 'frama-c/server';
 import * as States from 'frama-c/states';
 
-import * as API from 'frama-c/plugins/dive/api';
+import * as API from './api';
 
 import Cytoscape from 'cytoscape';
 import CytoscapeComponent from 'react-cytoscapejs';
@@ -63,6 +63,11 @@ interface CytoscapeExtended extends Cytoscape.Core {
   panzoom(options: unknown): void;
 }
 
+type Identified = { id: string }
+type NodeData = Cytoscape.NodeDataDefinition & Identified
+type EdgeData = { id: string;[key: string]: unknown }
+type NodeOrId = string | Cytoscape.NodeSingular
+
 function callstackToString(callstack: API.callstack): string {
   return callstack.map((cs) => `${cs.fun}:${cs.instr}`).join('/');
 }
@@ -167,20 +172,18 @@ class Dive {
         if (context) {
           (this.cy.style() as any).selector('node').style('width',
             (node: any) => {
-            const fStyle = node.pstyle('font-style').strValue;
-            const weight = node.pstyle('font-weight').strValue;
-            const size = node.pstyle('font-size').pfValue;
-            const family = node.pstyle('font-family').strValue;
-            context.font = `${fStyle} ${weight} ${size}px ${family}`;
-            const width = context.measureText(node.data('label')).width;
-            return `${Math.max(min, width + padding)}px`;
-          });
+              const fStyle = node.pstyle('font-style').strValue;
+              const weight = node.pstyle('font-weight').strValue;
+              const size = node.pstyle('font-size').pfValue;
+              const family = node.pstyle('font-family').strValue;
+              context.font = `${fStyle} ${weight} ${size}px ${family}`;
+              const width = context.measureText(node.data('label')).width;
+              return `${Math.max(min, width + padding)}px`;
+            });
         }
       }
     }
     /* eslint-enable @typescript-eslint/no-explicit-any */
-
-    this.refresh();
   }
 
   onCxtMenu(node: Cytoscape.NodeSingular): Cxtcommand[] {
@@ -189,7 +192,7 @@ class Dive {
     buildCxtMenu(commands,
       <><div className="fas fa-binoculars fa-2x" />Explore</>,
       () => { this.explore(node); });
-    if (data.kind === 'composite')
+    if (data.nkind === 'composite')
       buildCxtMenu(commands,
         <><div className="fa fa-expand-arrows-alt fa-2x" />Unfold</>);
     else
@@ -304,84 +307,100 @@ class Dive {
       timeout = setTimeout(() => {
         tips?.forEach((tip) => tip.hide());
         tips = null; // Force rebuilding tips in case they changed
-      }, 1000);
+      }, 0);
     });
   }
 
-  receiveGraph(data: API.graphData): Cytoscape.CollectionReturnValue {
-    let newNodes = this.cy.collection();
+  updateElement(group: Cytoscape.ElementGroup, data: NodeData | EdgeData):
+    Cytoscape.CollectionReturnValue {
+    let element = this.cy.$id(data.id);
+    if (element.nonempty()) {
+      element.removeData();
+      element.data(data);
+    }
+    else {
+      element = this.cy.add({ group, data });
+      element.addClass("new");
+    }
+    element.removeClass("stale");
+    return element;
+  }
 
-    for (const node of data.nodes) {
-      const data : { [k: string]: unknown } = { ...node};
-      if (typeof node.range === 'number')
-        data.stops = `0% ${node.range}% ${node.range}% 100%`;
+  updateNode(data: NodeData):
+    Cytoscape.NodeSingular {
+      const element = this.updateElement("nodes", data);
+      element.addClass('node');
+      return element;
+  }
 
-      let ele = this.cy.$id(node.id.toString());
-      if (ele.nonempty()) {
-        ele.removeData();
-        ele.data(data);
-        ele.neighborhood('edge').remove();
-      }
-      else {
-        if (node.locality.callstack)
-          data.parent = this.referenceCallstack(node.locality.callstack)?.id();
-        else
-          data.parent = this.referenceFile(node.locality.file).id();
-
-        ele = this.cy.add({group: 'nodes', data, classes: 'new'});
-        this.addTips(ele);
-        newNodes = ele.union(newNodes);
-      }
+  updateEdge(src: NodeOrId, dst: NodeOrId, data: EdgeData):
+    Cytoscape.EdgeSingular {
+    const source = typeof src === "string" ? src : src.id();
+    const target = typeof dst === "string" ? dst : dst.id();
+    data = { ...data, source, target };
+    const element = this.updateElement("edges", data);
+    element.addClass('dependency');
+    return element;
+  }
 
-      // Add a node for the user to ask for more dependencies
-      const idmore = `${node.id}-more`;
-      this.cy.$id(idmore).remove();
-      if (node.backward_explored === 'partial') {
-        const elemore = this.cy.add({
-          group: 'nodes',
-          data: { id: idmore, parent: ele.data('parent') },
-          classes: 'new more',
-        });
-        newNodes = elemore.union(newNodes);
-        this.cy.add({
-          group: 'edges',
-          data: { source: idmore, target: node.id },
-          classes: 'new',
-        });
-      }
-    }
+  updateNodeData(node: API.node): void {
+    const data = { ...node, id: `${node.id}` } as NodeData;
 
-    for (const dep of data.deps) {
-      const src = this.cy.$id(dep.src.toString());
-      const dst = this.cy.$id(dep.dst.toString());
-      this.cy.add({
-        data: {
-          ...(dep as { [k: string]: unknown }),
-          source: dep.src,
-          target: dep.dst
-        },
-        group: 'edges',
-        classes: src?.hasClass('new') || dst?.hasClass('new') ? 'new' : '',
-      });
+    // Interval range visualization (see cytoscape stops style property)
+    if (typeof node.range === 'number')
+      data.stops = `0% ${node.range}% ${node.range}% 100%`;
+
+    // Build clusters for this node if needed
+    if (node.locality.callstack)
+      data.parent = this.referenceCallstack(node.locality.callstack)?.id();
+    else
+      data.parent = this.referenceFile(node.locality.file).id();
+
+    // Add new node or update existing node
+    const ele = this.updateNode(data);
+    if (ele.hasClass("new"))
+      this.addTips(ele);
+
+    // Add a node for the user to ask for more dependencies
+    const idmore = `${node.id}-more`;
+    if (node.backward_explored === 'partial') {
+      const elemore = this.updateNode({ id: idmore, parent: data.parent });
+      elemore.addClass("more");
+      this.updateEdge(elemore, ele, { id: `e${node.id}-more` });
     }
+    else {
+      this.cy.$id(idmore).remove();
+    }
+  }
 
-    return newNodes;
+  updateEdgeData(edge: API.dependency): void {
+    const data = { ...edge, id: `e${edge.id}` } as EdgeData;
+    this.updateEdge(`${edge.src}`, `${edge.dst}`, data);
   }
 
-  receiveData(data: API.diffData): Cytoscape.NodeSingular | undefined {
+  updateGraph(data: API.graphData[]): void {
     this.cy.startBatch();
+    this.cy.$('.node, .dependency').addClass('stale');
 
-    for (const id of data.sub)
-      this.remove(this.cy.$id(id.toString()));
+    // Update vertices
+    for (const d of data) {
+      if ('nkind' in d.element) // Node
+        this.updateNodeData(d.element);
+    }
 
-    const newNodes = this.receiveGraph(data.add);
+    // Edges must be updated after vertices since their sources and destination
+    // must have been created beforhand
+    for (const d of data) {
+      if ('dkind' in d.element) // Dependency
+        this.updateEdgeData(d.element);
+    }
 
-    this.cy.endBatch();
+    // Remove nodes that are not present anymore
+    this.cy.$('.stale').forEach(n => this.remove(n));
 
-    this.recomputeLayout(newNodes);
+    this.cy.endBatch();
 
-    const root = data.root;
-    return root ? this.cy.$id(root.toString()) : undefined;
+    this.recomputeLayout(this.cy.$('node.new'));
   }
 
   get layout(): string {
@@ -423,14 +442,15 @@ class Dive {
   }
 
   async exec<In>(
-    request: Server.ExecRequest<In, API.diffData | null>,
+    request: Server.ExecRequest<In, number | undefined | null>,
     param: In): Promise<Cytoscape.NodeSingular | undefined> {
     try {
       if (Server.isRunning()) {
         await this.setMode();
-        const data = await Server.send(request, param);
-        if (data)
-          return this.receiveData(data);
+        const r = await Server.send(request, param);
+        if (r) {
+          return undefined;
+        }
       }
     }
     catch (err) {
@@ -440,21 +460,6 @@ class Dive {
     return undefined;
   }
 
-  async refresh(): Promise<void> {
-    try {
-      if (Server.isRunning()) {
-        const data = await Server.send(API.graph, {});
-        this.cy.startBatch();
-        const newNodes = this.receiveGraph(data);
-        this.cy.endBatch();
-        this.recomputeLayout(newNodes);
-      }
-    }
-    catch (err) {
-      Debug.error(err);
-    }
-  }
-
   static async setWindow(window: API.explorationWindow): Promise<void> {
     if (Server.isRunning())
       await Server.send(API.window, window);
@@ -573,10 +578,11 @@ type GraphViewRef = {
 
 const GraphView = React.forwardRef<GraphViewRef | undefined, GraphViewProps>(
   (props: GraphViewProps, ref) => {
-  const {lock, layout, selectionMode} = props;
+  const { lock, layout, selectionMode } = props;
 
   const [dive, setDive] = useState(() => new Dive());
   const [selection, updateSelection] = States.useSelection();
+  const graph = States.useSyncArrayData(API.graph);
 
   function setCy(cy: Cytoscape.Core): void {
     if (cy !== dive.cy)
@@ -586,12 +592,16 @@ const GraphView = React.forwardRef<GraphViewRef | undefined, GraphViewProps>(
   useImperativeHandle(ref, () => ({ clear: () => dive.clear() }));
 
   useEffect(() => {
-    setDive(new Dive(dive.cy));
+    setDive(new Dive(dive.cy)); // On hot reload, setup a new instance
   }, [Dive]); // eslint-disable-line react-hooks/exhaustive-deps
 
   useEffect(() => {
     dive.layout = layout;
-  }, [dive, layout]); // eslint-disable-line react-hooks/exhaustive-deps
+  }, [dive, layout]);
+
+  useEffect(() => {
+    dive.updateGraph(graph);
+  }, [dive, graph]);
 
   // Follow mode
   useEffect(() => {
diff --git a/ivette/src/frama-c/plugins/dive/style.json b/ivette/src/frama-c/plugins/dive/style.json
index ff9498762f52fa09bf66fe501ee44c427029e7a6..79a9907c1e06fd4d0f2841f0d5a4e2fd8e17f16a 100644
--- a/ivette/src/frama-c/plugins/dive/style.json
+++ b/ivette/src/frama-c/plugins/dive/style.json
@@ -143,7 +143,7 @@
     }
   },
   {
-    "selector": "node[kind='const']",
+    "selector": "node[nkind='const']",
     "style": {
       "shape": "ellipse",
       "background-color": "#bbb",
@@ -152,7 +152,7 @@
     }
   },
   {
-    "selector": "node[kind='alarm']",
+    "selector": "node[nkind='alarm']",
     "style": {
       "shape": "octagon",
       "background-color": "#f00",
@@ -160,13 +160,13 @@
     }
   },
   {
-    "selector": "node[kind='scattered']",
+    "selector": "node[nkind='scattered']",
     "style": {
       "shape": "rhomboid"
     }
   },
   {
-    "selector": "node[kind='composite']",
+    "selector": "node[nkind='composite']",
     "style": {
       "ghost": "yes",
       "ghost-offset-x": "6px",
@@ -191,7 +191,7 @@
     }
   },
   {
-    "selector": "edge[kind='callee']",
+    "selector": "edge[nkind='callee']",
     "style": {
       "line-color": "#8f8",
       "target-arrow-color": "#8f8"
diff --git a/ivette/src/frama-c/plugins/eva/Coverage.tsx b/ivette/src/frama-c/plugins/eva/Coverage.tsx
index cad3b95c3560ed073255ce6986df945123b196e8..0a048970850663ee84404e3c369409b220e97509 100644
--- a/ivette/src/frama-c/plugins/eva/Coverage.tsx
+++ b/ivette/src/frama-c/plugins/eva/Coverage.tsx
@@ -22,14 +22,12 @@
 
 import React from 'react';
 import { Table, Column } from 'dome/table/views';
-import { CompactModel } from 'dome/table/arrays';
 import * as Arrays from 'dome/table/arrays';
 import * as Compare from 'dome/data/compare';
 import * as Ivette from 'ivette';
 import * as States from 'frama-c/states';
-
-import * as Ast from 'frama-c/kernel/api/ast';
 import * as Eva from 'frama-c/plugins/eva/api/general';
+
 import CoverageMeter, { percent } from './CoverageMeter';
 
 type stats = Eva.functionStatsData;
@@ -70,21 +68,15 @@ const ordering: Arrays.ByColumns<stats> = {
   ),
 };
 
-class Model extends CompactModel<Ast.fct, stats> {
-  constructor() {
-    super(Eva.functionStats.getkey);
-    this.setColumnOrder(ordering);
-    this.setSorting({ sortBy: 'coverage', sortDirection: 'ASC' });
-  }
-}
-
 export function CoverageTable(): JSX.Element {
-  const data = States.useSyncArray(Eva.functionStats).getArray();
-  const [selection, updateSelection] = States.useSelection();
 
-  const model = React.useMemo(() => new Model(), []);
-  React.useEffect(() => model.replaceAllDataWith(data), [model, data]);
+  const model = States.useSyncArrayModel(Eva.functionStats);
+  React.useEffect(() => {
+    model.setColumnOrder(ordering);
+    model.setSorting({ sortBy: 'coverage', sortDirection: 'ASC' });
+  }, [model]);
 
+  const [selection, updateSelection] = States.useSelection();
   const onSelection = ({ key }: stats): void => {
     updateSelection({ location: { fct: key } });
   };
diff --git a/ivette/src/frama-c/plugins/eva/EvaReady/index.tsx b/ivette/src/frama-c/plugins/eva/EvaReady/index.tsx
index aacc53e93e910eb182f1e3713ffdd9e02d4c82b2..026a9e3396ddcd55ef300027690ac99a7a86b691 100644
--- a/ivette/src/frama-c/plugins/eva/EvaReady/index.tsx
+++ b/ivette/src/frama-c/plugins/eva/EvaReady/index.tsx
@@ -20,16 +20,40 @@
 /*                                                                          */
 /* ************************************************************************ */
 
-import React from 'react';
+import React, { useEffect } from 'react';
+import { GlobalState, useGlobalState } from 'dome/data/states';
 import * as States from 'frama-c/states';
+import { Button } from 'dome/controls/buttons';
 import * as Eva from 'frama-c/plugins/eva/api/general';
 import Gallery from 'dome/controls/gallery.json';
 
 import gearsIcon from '../images/gears.svg';
 import './style.css';
+import { onSignal } from 'frama-c/server';
 
-const EvaReady: React.FC = ({children}) => {
+class AckAbortedState extends GlobalState<boolean> {
+  #signalHookSet = false;
+
+  constructor(initValue: boolean) {
+    super(initValue);
+  }
+
+  setupSignalHooks(): void {
+    if (!this.#signalHookSet) {
+      onSignal(Eva.signalComputationState,
+        () => this.setValue(false));
+      this.#signalHookSet = true;
+    }
+  }
+}
+
+const ackAbortedState = new AckAbortedState(false);
+
+const EvaReady: React.FC = ({ children }) => {
   const state = States.useSyncValue(Eva.computationState);
+  const [ackAborted, setAckAborted] = useGlobalState(ackAbortedState);
+
+  useEffect(() => ackAbortedState.setupSignalHooks());
 
   switch (state) {
     case undefined:
@@ -55,6 +79,27 @@ const EvaReady: React.FC = ({children}) => {
 
     case 'computed':
       return <>{children}</>;
+
+    case 'aborted':
+      if (ackAborted) {
+        return <>{children}</>;
+      }
+      else {
+        return (
+          <div className="eva-status">
+            <span>
+              The Eva analysis has been prematurely aborted by an internal error
+              or a user interruption:
+              the displayed results will be incomplete.
+            </span>
+            <Button
+              label="Ok"
+              style={{ width: "2cm" }}
+              onClick={() => setAckAborted(true)}
+            />
+          </div>
+        );
+      }
   }
 };
 
diff --git a/ivette/src/frama-c/plugins/eva/EvaReady/style.css b/ivette/src/frama-c/plugins/eva/EvaReady/style.css
index fc2ae05a94d573ef039370d715a8d8f42a602ee9..6a68bead536b05aed50bd41f595f50aac2750057 100644
--- a/ivette/src/frama-c/plugins/eva/EvaReady/style.css
+++ b/ivette/src/frama-c/plugins/eva/EvaReady/style.css
@@ -3,7 +3,7 @@
   flex-direction: column;
   gap: 20px;
   align-items: center;
-  margin:auto;
+  margin:10%;
 }
 
 .eva-status-icon {
@@ -17,6 +17,10 @@
   text-align: center;
 }
 
+.eva-status button {
+  margin: auto;
+}
+
 .eva-status-computing {
   font-weight: bold;
 }
diff --git a/ivette/src/frama-c/plugins/eva/api/general/index.ts b/ivette/src/frama-c/plugins/eva/api/general/index.ts
index a603305fa2d62dae367492959ab5ebbb360583f5..681fa6de976e04dacd381a9b1626ae76cf8a8ee5 100644
--- a/ivette/src/frama-c/plugins/eva/api/general/index.ts
+++ b/ivette/src/frama-c/plugins/eva/api/general/index.ts
@@ -63,14 +63,16 @@ import { tag } from 'frama-c/kernel/api/data';
 import { tagDefault } from 'frama-c/kernel/api/data';
 
 /** State of the computation of Eva Analysis. */
-export type computationStateType = "not_computed" | "computing" | "computed";
+export type computationStateType =
+  "not_computed" | "computing" | "computed" | "aborted";
 
 /** Decoder for `computationStateType` */
 export const jComputationStateType: Json.Decoder<computationStateType> =
-  Json.jUnion<"not_computed" | "computing" | "computed">(
+  Json.jUnion<"not_computed" | "computing" | "computed" | "aborted">(
     Json.jTag("not_computed"),
     Json.jTag("computing"),
     Json.jTag("computed"),
+    Json.jTag("aborted"),
   );
 
 /** Natural order for `computationStateType` */
@@ -130,11 +132,21 @@ const getCallers_internal: Server.GetRequest<fct,CallSite[]> = {
   name:   'plugins.eva.general.getCallers',
   input:  jFct,
   output: Json.jArray(jCallSite),
-  signals: [],
+  signals: [ { name: 'plugins.eva.general.signalComputationState' } ],
 };
 /** Get the list of call site of a function */
 export const getCallers: Server.GetRequest<fct,CallSite[]>= getCallers_internal;
 
+const getCallees_internal: Server.GetRequest<marker,fct[]> = {
+  kind: Server.RqKind.GET,
+  name:   'plugins.eva.general.getCallees',
+  input:  jMarker,
+  output: Json.jArray(jFct),
+  signals: [ { name: 'plugins.eva.general.signalComputationState' } ],
+};
+/** Return the functions pointed to by a function pointer */
+export const getCallees: Server.GetRequest<marker,fct[]>= getCallees_internal;
+
 /** Data for array rows [`functions`](#functions)  */
 export interface functionsData {
   /** Entry identifier. */
@@ -243,7 +255,7 @@ const getDeadCode_internal: Server.GetRequest<fct,deadCode> = {
   name:   'plugins.eva.general.getDeadCode',
   input:  jFct,
   output: jDeadCode,
-  signals: [],
+  signals: [ { name: 'plugins.eva.general.signalComputationState' } ],
 };
 /** Get the lists of unreachable and of non terminating statements in a function */
 export const getDeadCode: Server.GetRequest<fct,deadCode>= getDeadCode_internal;
@@ -318,7 +330,7 @@ const taintedLvalues_internal: Server.GetRequest<fct,LvalueTaints[]> = {
   name:   'plugins.eva.general.taintedLvalues',
   input:  jFct,
   output: Json.jArray(jLvalueTaints),
-  signals: [],
+  signals: [ { name: 'plugins.eva.general.signalComputationState' } ],
 };
 /** Get the tainted lvalues of a given function */
 export const taintedLvalues: Server.GetRequest<fct,LvalueTaints[]>= taintedLvalues_internal;
@@ -690,7 +702,7 @@ const getStates_internal: Server.GetRequest<
   input:  Json.jPair( jMarker, Json.jBoolean,),
   output: Json.jArray(
             Json.jTriple( Json.jString, Json.jString, Json.jString,)),
-  signals: [],
+  signals: [ { name: 'plugins.eva.general.signalComputationState' } ],
 };
 /** Get the domain states about the given marker */
 export const getStates: Server.GetRequest<
diff --git a/ivette/src/frama-c/plugins/eva/api/values/index.ts b/ivette/src/frama-c/plugins/eva/api/values/index.ts
index 5991da5fa400387532a0b749de91715a1bb82985..05e2360e485e0cef0436d720245b9877ff20b9b3 100644
--- a/ivette/src/frama-c/plugins/eva/api/values/index.ts
+++ b/ivette/src/frama-c/plugins/eva/api/values/index.ts
@@ -122,8 +122,8 @@ export const getStmtInfo: Server.GetRequest<
 
 const getProbeInfo_internal: Server.GetRequest<
   marker,
-  { evaluable: boolean, code?: string, stmt?: marker, rank: number,
-    effects: boolean, condition: boolean }
+  { evaluable: boolean, code?: string, stmt?: marker, effects: boolean,
+    condition: boolean }
   > = {
   kind: Server.RqKind.GET,
   name:   'plugins.eva.values.getProbeInfo',
@@ -132,7 +132,6 @@ const getProbeInfo_internal: Server.GetRequest<
             evaluable: Json.jBoolean,
             code: Json.jOption(Json.jString),
             stmt: Json.jOption(jMarker),
-            rank: Json.jNumber,
             effects: Json.jBoolean,
             condition: Json.jBoolean,
           }),
@@ -141,8 +140,8 @@ const getProbeInfo_internal: Server.GetRequest<
 /** Probe informations */
 export const getProbeInfo: Server.GetRequest<
   marker,
-  { evaluable: boolean, code?: string, stmt?: marker, rank: number,
-    effects: boolean, condition: boolean }
+  { evaluable: boolean, code?: string, stmt?: marker, effects: boolean,
+    condition: boolean }
   >= getProbeInfo_internal;
 
 /** Evaluation of an expression or lvalue */
diff --git a/ivette/src/frama-c/plugins/eva/valuetable.tsx b/ivette/src/frama-c/plugins/eva/valuetable.tsx
index 92da070f66b5096a41eff374af01f6dd8b8e829d..95a83acbc7044e37a0de10da29d3254b55f1f7ab 100644
--- a/ivette/src/frama-c/plugins/eva/valuetable.tsx
+++ b/ivette/src/frama-c/plugins/eva/valuetable.tsx
@@ -59,7 +59,7 @@ function getAlarmStatus(alarms: Alarm[] | undefined): string {
 }
 
 type MarkerTracked = [ 'Tracked', boolean ]
-type MarkerPinned  = [ 'Pinned' , boolean ]
+type MarkerPinned  = [ 'Pinned', boolean ]
 type MarkerStatus  = MarkerTracked | MarkerPinned | 'JustFocused'
 
 function MarkerStatusClass(status: MarkerStatus): string {
@@ -211,18 +211,22 @@ function useProbeCache(): Request<Location, Probe> {
 /* -------------------------------------------------------------------------- */
 
 interface StmtProps {
+  fct?: string;
   stmt?: Ast.marker;
   marker?: Ast.marker;
   short?: boolean;
 }
 
 function Stmt(props: StmtProps): JSX.Element | null {
-  const { stmt, marker, short } = props;
-  const { descr, sloc: { base, line } } = States.useMarker(marker);
-  if (!stmt || !marker) return null;
-  const label = short ? `@L${line}` : `@${base}:${line}`;
+  const { fct, stmt, marker, short } = props;
+  const { descr } = States.useMarker(stmt);
+  const { sloc } = States.useMarker(marker);
+  if (!marker || !fct) return null;
+  // Location sloc should always be defined for statements.
+  const label = short ? `@L${sloc?.line}` : `@${sloc?.base}:${sloc?.line}`;
+  const title = stmt ? descr : "Start of function " + fct;
   const className = 'dome-text-cell eva-stmt';
-  return <span className={className} title={descr}>{label}</span>;
+  return <span className={className} title={title}>{label}</span>;
 }
 
 /* -------------------------------------------------------------------------- */
@@ -289,7 +293,7 @@ async function StackInfos(props: StackInfosProps): Promise<JSX.Element> {
         onDoubleClick={onDoubleClick}
       >
         {caller}
-        <Stmt stmt={stmt} marker={stmt} />
+        <Stmt fct={caller} stmt={stmt} marker={stmt} />
       </Cell>
     );
   };
@@ -343,7 +347,7 @@ function ProbeHeader(props: ProbeHeaderProps): JSX.Element {
 
   const isPinned = isPinnedMarker(status);
   const pinText = isPinned ? 'Unpin' : 'Pin';
-  const loc: States.SelectionActions = { location: { fct, marker: target} };
+  const loc: States.SelectionActions = { location: { fct, marker: target } };
   const onClick = (): void => { setSelection(loc); selectProbe(); };
   const onDoubleClick = (): void => pinProbe(!isPinned);
   const onContextMenu = (): void => {
@@ -385,7 +389,7 @@ function ProbeHeader(props: ProbeHeaderProps): JSX.Element {
         <div className='eva-header-text-overflow'>
           <span className='dome-text-cell' title={code}>{code}</span>
         </div>
-        <Stmt stmt={stmt} marker={target} short={true}/>
+        <Stmt fct={fct} stmt={stmt} marker={target} short={true}/>
       </TableCell>
     </th>
   );
@@ -411,17 +415,22 @@ function ProbeDescr(props: ProbeDescrProps): JSX.Element[] {
   const valuesClass = classes('eva-table-values', 'eva-table-values-center');
   const tableClass = classes('eva-table-descrs', 'eva-table-descr-sticky');
   const cls = classes(valuesClass, tableClass);
-  const title = (s: string): string => `Values ${s} the statement evaluation`;
   const elements: JSX.Element[] = [];
   function push(title: string, children: JSX.Element | string): void {
     elements.push(<td className={cls} title={title}>{children}</td>);
   }
-  if (!probe.effects && !probe.condition)
-    push('Values at the statement', '-');
+  if (!probe.effects && !probe.condition) {
+    if (probe.stmt)
+      push('Values at the statement', '-');
+    else if (probe.fct)
+      push('Values at the start of function ' + probe.fct, '-');
+    else
+      push('Values at the start of the analysis', '-');
+  }
   if (probe.effects || probe.condition)
-    push(title('before'), 'Before');
+    push('Values just before the statement', 'Before');
   if (probe.effects)
-    push(title('after'), 'After');
+    push('Values just after the statement', 'After');
   if (probe.condition) {
     const pushCondition = (s: string): void => {
       const t = `Values after the condition, in the ${s.toLowerCase()} branch`;
@@ -963,7 +972,7 @@ function useEvaluationMode(props: EvaluationModeProps): void {
 /* -------------------------------------------------------------------------- */
 
 /* Table's state. It is global for when the user changes the view. */
-const CallstackState = new GlobalState<callstack>('Summary');
+export const CallstackState = new GlobalState<callstack>('Summary');
 const FunctionsManagerState = new GlobalState(new FunctionsManager());
 const FocusState = new GlobalState<Probe | undefined>(undefined);
 
@@ -1032,7 +1041,7 @@ function EvaTable(): JSX.Element {
   /* On meta-selection, pin the selected location. */
   React.useEffect(() => {
     const pin = (loc: States.Location): void => {
-      const {marker, fct} = loc;
+      const { marker, fct } = loc;
       if (marker && fct) setLocPin({ target: marker, fct }, true);
     };
     States.MetaSelection.on(pin);
diff --git a/ivette/src/frama-c/server.ts b/ivette/src/frama-c/server.ts
index 2d404a244c3fa91dfacbc3135df8d727def34985..9d2ff03677098da45328e952a7af094b664b93b7 100644
--- a/ivette/src/frama-c/server.ts
+++ b/ivette/src/frama-c/server.ts
@@ -39,7 +39,7 @@ import * as Json from 'dome/data/json';
 import { RichTextBuffer } from 'dome/text/buffers';
 import { ChildProcess } from 'child_process';
 import { client } from './client_socket';
-//import { client } from './client_zmq';
+// import { client } from './client_zmq';
 
 // --------------------------------------------------------------------------
 // --- Server Status
@@ -284,6 +284,8 @@ export function stop(): void {
   }
 }
 
+Dome.atExit(stop);
+
 // --------------------------------------------------------------------------
 // --- Server Control (Kill)
 // --------------------------------------------------------------------------
@@ -474,6 +476,9 @@ async function _launch(): Promise<void> {
     env,
   };
   // Launch Process
+  System.atExit(() => {
+    sockaddr && System.remove(sockaddr);
+  });
   process = await System.spawn(command, params, options);
   const logger = (text: string | string[]): void => {
     buffer.append(text);
diff --git a/ivette/src/frama-c/states.ts b/ivette/src/frama-c/states.ts
index ca134d60ac1894ab2e33ffc1218de8b3d7071da4..1ff4fadc9ba31801b70fd96a2519b316b43cbc93 100644
--- a/ivette/src/frama-c/states.ts
+++ b/ivette/src/frama-c/states.ts
@@ -38,6 +38,7 @@ import { Client, useModel } from 'dome/table/models';
 import { CompactModel } from 'dome/table/arrays';
 import * as Ast from 'frama-c/kernel/api/ast';
 import * as Server from './server';
+import * as Status from 'frama-c/kernel/Status';
 
 // --------------------------------------------------------------------------
 // --- Pretty Printing (Browser Console)
@@ -293,12 +294,14 @@ class SyncArray<K, A> {
   handler: Array<K, A>;
   upToDate: boolean;
   fetching: boolean;
+  signaled: boolean; // during fetching or offline
   model: CompactModel<K, A>;
 
   constructor(h: Array<K, A>) {
     this.handler = h;
     this.fetching = false;
     this.upToDate = false;
+    this.signaled = false;
     this.model = new CompactModel(h.getkey);
     this.model.setNaturalOrder(h.order);
     this.fetch = this.fetch.bind(this);
@@ -316,12 +319,16 @@ class SyncArray<K, A> {
   }
 
   async fetch(): Promise<void> {
-    if (this.fetching || !Server.isRunning()) return;
+    if (this.fetching || !Server.isRunning()) {
+      this.signaled = true;
+      return;
+    }
     try {
       this.fetching = true;
       let pending;
       /* eslint-disable no-await-in-loop */
       do {
+        this.signaled = false;
         const data = await Server.send(this.handler.fetch, 20000);
         const { reload = false, removed = [], updated = [] } = data;
         const { model } = this;
@@ -331,7 +338,7 @@ class SyncArray<K, A> {
         if (reload || updated.length > 0 || removed.length > 0)
           model.reload();
         pending = data.pending ?? 0;
-      } while (pending > 0);
+      } while (this.signaled || pending > 0);
       /* eslint-enable no-await-in-loop */
     } catch (error) {
       D.error(
@@ -339,6 +346,7 @@ class SyncArray<K, A> {
         error,
       );
     } finally {
+      this.signaled = false;
       this.fetching = false;
       this.upToDate = true;
     }
@@ -348,6 +356,7 @@ class SyncArray<K, A> {
     try {
       this.model.clear();
       this.upToDate = false;
+      this.signaled = false;
       if (Server.isRunning()) {
         await Server.send(this.handler.reload, null);
         this.fetch();
@@ -393,27 +402,95 @@ export function reloadArray<K, A>(arr: Array<K, A>): void {
   currentSyncArray(arr).reload();
 }
 
+/** Access to Synchronized Array elements. */
+export interface ArrayProxy<K, A> {
+  length: number;
+  getData(elt: K | undefined): (A | undefined);
+  forEach(fn: (row: A, elt: K) => void): void;
+}
+
+// --- Utility functions
+
+function arrayGet<K, A>(
+  model: CompactModel<K, A>,
+  elt: K | undefined,
+  _stamp: number,
+): A | undefined {
+  return elt ? model.getData(elt) : undefined;
+}
+
+function arrayProxy<K, A>(
+  model: CompactModel<K, A>,
+  _stamp: number,
+): ArrayProxy<K, A> {
+  return {
+    length: model.length(),
+    getData: (elt) => elt ? model.getData(elt) : undefined,
+    forEach: (fn) => model.forEach((r) => fn(r, model.getkey(r))),
+  };
+}
+
+// ---- Hooks
+
 /**
-   Use Synchronized Array (Custom React Hook).
+   Use Synchronized Array as a low level, ready to use, Table Compact Model.
 
-   Unless specified, the hook makes the component re-render on every
-   update. Disabling this automatic re-rendering can be an option when
-   using the model to make a table view, which automatically synchronizes on
-   model updates.
-   @param sync Whether the component re-renders on updates (default is `true`).
+   Warning: to be in sync with the array, one shall subscribe to model events,
+   eg. by using `useModel()` hook, like `<Table/>` element does.
  */
-export function useSyncArray<K, A>(
-  arr: Array<K, A>,
-  sync = true,
+export function useSyncArrayModel<K, A>(
+  arr: Array<K, A>
 ): CompactModel<K, A> {
   Server.useStatus();
   const st = currentSyncArray(arr);
   Server.useSignal(arr.signal, st.fetch);
   st.online();
-  useModel(st.model, sync);
   return st.model;
 }
 
+/** Use Synchronized Array as a data array. */
+export function useSyncArrayData<K, A>(arr: Array<K, A>): A[]
+{
+  return useSyncArrayModel(arr).getArray();
+}
+
+/** Use Synchronized Array element. */
+export function useSyncArrayElt<K, A>(
+  arr: Array<K, A>,
+  elt: K | undefined,
+): A | undefined {
+  const model = useSyncArrayModel(arr);
+  const stamp = useModel(model);
+  return React.useMemo(
+    () => arrayGet(model, elt, stamp),
+    [model, elt, stamp]
+  );
+}
+
+/** Use Synchronized Array as an element data getter. */
+export function useSyncArrayGetter<K, A>(
+  arr: Array<K, A>
+): (elt: K | undefined) => (A | undefined) {
+  const model = useSyncArrayModel(arr);
+  const stamp = useModel(model);
+  return React.useCallback(
+    (elt) => arrayGet(model, elt, stamp),
+    [model, stamp]
+  );
+}
+
+/** Use Synchronized Array as an array proxy. */
+export function useSyncArrayProxy<K, A>(
+  arr: Array<K, A>
+): ArrayProxy<K, A> {
+  const model = useSyncArrayModel<K, A>(arr);
+  const stamp = useModel(model);
+  return React.useMemo(
+    () => arrayProxy(model, stamp),
+    [model, stamp]
+  );
+}
+
 /**
    Return the associated array model.
 */
@@ -713,6 +790,14 @@ export function useSelection(): [Selection, (a: SelectionActions) => void] {
   const [current, setCurrent] = useGlobalState(GlobalSelection);
   const callback = React.useCallback((action) => {
     setCurrent(reducer(current, action));
+    if (isMultipleSelect(action)) {
+      const l = action.locations.length;
+      const markers =
+        (l > 1) ? `${l} markers selected, listed in the 'Locations' panel` :
+          (l === 1) ? `1 marker selected` : `no markers selected`;
+      const text = `${action.name}: ${markers}`;
+      Status.setMessage({ text, title: action.title, kind: 'success' });
+    }
   }, [current, setCurrent]);
   return [current, callback];
 }
@@ -741,11 +826,8 @@ export type attributes = Ast.markerAttributesData;
 
 /** Access the marker attributes from AST. */
 export function useMarker(marker: Ast.marker | undefined): attributes {
-  const marks = useSyncArray(Ast.markerAttributes);
-  if (marker === undefined) return Ast.markerAttributesDataDefault;
-  const attrs = marks.getData(marker);
-  if (attrs === undefined) return Ast.markerAttributesDataDefault;
-  return attrs;
+  const marks = useSyncArrayElt(Ast.markerAttributes, marker);
+  return marks ?? Ast.markerAttributesDataDefault;
 }
 
 // --------------------------------------------------------------------------
diff --git a/ivette/src/renderer/Laboratory.tsx b/ivette/src/renderer/Laboratory.tsx
index 238b5030ae608ab7cb22d4c0798faf07e9edb8a5..b65ef04c0f4884ce2c180770d3bbe17673f4e66f 100644
--- a/ivette/src/renderer/Laboratory.tsx
+++ b/ivette/src/renderer/Laboratory.tsx
@@ -253,34 +253,40 @@ const makeGridItem = (customize: unknown, onClose: (id: string) => void) =>
 type Shape = Json.json // Until Grids has a type Shape, use this one instead
 
 interface CustomViewsProps {
-  settings?: string,
+  settings: string,
   shape: Shape,
   setShape: (shape: Shape) => void,
   views: React.PropsWithChildren<View>[]
 }
 
-interface CustomViewsSettings {
-  current?: string;
-  shapes?: { [k: string]: Shape };
-}
+type CustomShapes = { [id: string]: Shape };
+type CustomViews = { [id: string]: View };
 
 function CustomViews(props: CustomViewsProps): JSX.Element {
   const { settings, shape, setShape, views: libViews } = props;
-  const [local, setLocal] = Settings.useWindowSettings<CustomViewsSettings>(
-    settings,
-    Json.identity as Json.Decoder<CustomViewsSettings & Json.json>, // Clearly abusive conversion, a real decoder is needed
+  const [current, setCurrent] = Settings.useWindowSettingsData<string>(
+    `${settings}.current`,
+    Json.jString,
+    Json.identity,
+    ''
+  );
+  const [shapes, setShapes] = Settings.useWindowSettingsData<CustomShapes>(
+    `${settings}.shapes`,
+    Json.identity as Json.Decoder<CustomShapes>,
+    Json.identity as Json.Encoder<CustomShapes>,
+    // Clearly abusive conversion, real encoder/decoder are needed
+    {},
+  );
+  const [customs, setCustoms] = Settings.useLocalStorageData<CustomViews>(
+    'frama-c.labview',
+    Json.identity as Json.Decoder<CustomViews>,
+    Json.identity as Json.Encoder<CustomViews>,
+    // Clearly abusive conversion, real encoder/decoder are needed
     {},
   );
-  const [customs, setCustoms] =
-    Settings.useLocalStorage<{ [id: string]: View }>(
-      'frama-c.labview',
-      Json.identity as Json.Decoder<{ [id: string]: View } & Json.json>, // Clearly abusive conversion, a real decoder is needed
-      {},
-    );
   const [edited, setEdited] = React.useState<string>();
   const triggerDefault = React.useRef<View>();
-  const { current, shapes = {} } = local;
-  const theViews: { [id: string]: View } = {};
+  const theViews: CustomViews = {};
 
   _.forEach(libViews, (view) => {
     const {
@@ -316,9 +322,12 @@ function CustomViews(props: CustomViewsProps): JSX.Element {
 
   const SELECT = (id: string): void => {
     if (id && current !== id) {
-      if (current) shapes[current] = shape;
-      setLocal({ current: id, shapes });
+      if (current) {
+        const newShapes = { ...shapes, [current]: shape };
+        setShapes(newShapes);
+      }
       setShape(shapes[id] || getDefaultShape(theViews[id]));
+      setCurrent(id);
     }
   };
 
@@ -329,8 +338,9 @@ function CustomViews(props: CustomViewsProps): JSX.Element {
     const isCustom = !view.builtin;
 
     const DEFAULT = (): void => {
-      shapes[id] = undefined;
-      setLocal({ current: id, shapes });
+      const newShapes = { ...shapes };
+      delete newShapes[id];
+      setShapes(newShapes);
       setShape(getDefaultShape(view));
     };
 
@@ -340,7 +350,7 @@ function CustomViews(props: CustomViewsProps): JSX.Element {
       const base = `custom.${view.origin}`;
       const stock = getStock(view.origin);
       let k = 1;
-      let newId = base;
+      let newId: string = base;
       while (theViews[newId]) {
         k += 1;
         newId = `${base}~${k}`;
@@ -349,7 +359,7 @@ function CustomViews(props: CustomViewsProps): JSX.Element {
       if (newOrder && newOrder.concat) newOrder = newOrder.concat([k]);
       let newLabel = `Custom ${stock.label}`;
       if (k > 1) newLabel += `~${k}`;
-      customs[newId] = {
+      const customView = {
         id: newId,
         label: newLabel,
         order: newOrder,
@@ -357,26 +367,46 @@ function CustomViews(props: CustomViewsProps): JSX.Element {
         origin: view.origin,
         builtin: false,
       };
-      setCustoms(customs);
-      if (current) shapes[current] = shape;
-      setLocal({ current: newId, shapes });
+      setCustoms({ ...customs, [newId]: customView });
+      const newShape =
+        isCurrent ? shape : (shapes[id] ?? getDefaultShape(view));
+      const newShapes = { ...shapes, [newId]: newShape };
+      setShapes(newShapes);
+      setShape(newShape);
+      setCurrent(newId);
       setEdited(newId);
     };
 
     const REMOVE = (): void => {
-      delete customs[id];
-      delete shapes[id];
-      setCustoms(customs);
-      const newCurrent = current === id ? undefined : current;
-      setLocal({ current: newCurrent, shapes });
+      const newCustoms = { ... customs };
+      const newShapes = { ... shapes };
+      delete newCustoms[id];
+      delete newShapes[id];
+      setCustoms(newCustoms);
+      setShapes(newShapes);
+      if (isCurrent) {
+        const newView =
+          (view.origin && theViews[view.origin]) ||
+          _.find(theViews, (v: View) => !!v.defaultView) ||
+          _.find(theViews, (v: View) => v.id !== current) ||
+          theViews[0];
+        const newId = newView.id;
+        const newShape = shapes[newId] || getDefaultShape(newView);
+        setCurrent(newId);
+        setShape(newShape);
+      }
     };
 
+    const onView = (action: string): string =>
+      isCurrent ? `${action} View` : `${action} View (${view.label})`;
+    const hasRename = !edited && isCustom;
+
     Dome.popupMenu([
-      { label: 'Rename View', display: (!edited && isCustom), onClick: RENAME },
+      { label: onView('Rename'), display: hasRename, onClick: RENAME },
       { label: 'Restore Default', display: isCurrent, onClick: DEFAULT },
-      { label: 'Duplicate View', onClick: DUPLICATE },
+      { label: onView('Duplicate'), onClick: DUPLICATE },
       'separator',
-      { label: 'Remove View', display: isCustom, onClick: REMOVE },
+      { label: onView('Remove'), display: isCustom, onClick: REMOVE },
     ]);
   };
 
@@ -384,9 +414,8 @@ function CustomViews(props: CustomViewsProps): JSX.Element {
     if (edited === id) {
       const RENAMED = (newLabel: string): void => {
         if (newLabel) {
-          const custom = Json.jObj(customs[id] as Json.json) || {};
-          if (custom) custom.label = newLabel;
-          setCustoms(customs);
+          const customView : View = customs[id];
+          setCustoms({ ...customs, [id]: { ...customView, label: newLabel } });
         }
         setEdited(undefined);
       };
@@ -508,7 +537,7 @@ function CustomGroup({
 
 interface CustomPanelProps {
   dnd?: DnD;
-  settings?: string;
+  settings: string;
   shape?: Shape;
   setShape: (shape: Shape) => void;
   setDragging: (id?: string) => void;
@@ -570,7 +599,7 @@ export interface LabViewProps {
   /** Show component panels. */
   customize?: boolean;
   /** Base settings identifier. */
-  settings?: string;
+  settings: string;
 }
 
 /**
diff --git a/man/frama-c.1 b/man/frama-c.1
index c960811ac632c5d687cd1e99f48651132a74b183..1864494be989d5e78d8c40bf2dd218d49980e1c7 100644
--- a/man/frama-c.1
+++ b/man/frama-c.1
@@ -1,6 +1,6 @@
 .\" Automatically generated by Pandoc 2.14.0.3
 .\"
-.TH "FRAMA-C" "1" "" "2023-02-13" ""
+.TH "FRAMA-C" "1" "" "2023-05-12" ""
 .hy
 .\"------------------------------------------------------------------------
 .\"                                                                        
@@ -15,13 +15,13 @@
 
 .\" DO NOT EDIT THIS FILE!
 .\" This man file has been generated from a Markdown file (frama-c.1.md)
-.\" using pandoc 2.0 or newer. To modify this file, edit the Markdown file
-.\" and run `make man/frama-c.1`.
+.\" using pandoc 2.0 or newer. To modify this file, edit the Markdown file,
+.\" run `dune build @check-man` and then `dune promote`.
 .SH NAME
 .PP
-frama-c[.byte] - a static analyzer for C programs
+frama-c - a static analyzer for C programs
 .PP
-frama-c-gui[.byte] - the graphical interface of frama-c
+frama-c-gui - the graphical interface of frama-c
 .SH SYNOPSIS
 .PP
 \f[B]frama-c\f[R] [ \f[I]options\f[R] ] \f[I]files\f[R]
@@ -45,9 +45,9 @@ will provide the full list of the plugins that are currently installed.
 \f[B]frama-c\f[R].
 It features the same options as the command-line version.
 .PP
-\f[B]frama-c.byte\f[R] and \f[B]frama-c-gui.byte\f[R] are the OCaml
-bytecode versions of the command-line and graphical user interface
-respectively.
+\f[B]ivette\f[R] is a new, Electron-based graphical user interface for
+\f[B]frama-c\f[R].
+It also features the same options as the command-line version.
 .PP
 By default, Frama-C recognizes \f[I].c\f[R] files as C files needing
 pre-processing and \f[I].i\f[R] files as C files having been already
@@ -435,13 +435,11 @@ outputs the directory where the Frama-C kernel library is installed.
 alias of \f[B]-print-share-path\f[R].
 .TP
 -print-plugin-path
-outputs the directory where Frama-C searches its plugins (can be
-overridden by the \f[B]FRAMAC_PLUGIN\f[R] variable and the
-\f[B]-add-path\f[R] option).
+outputs the directory where Frama-C searches its plugins.
 .TP
 -print-share-path
-outputs the directory where Frama-C stores its data (can be overridden
-by the \f[B]FRAMAC_SHARE\f[R] variable).
+outputs the directory where Frama-C stores shareable files
+(e.g.\ standard library, machdeps, shared Makefiles).
 .TP
 [-no]-remove-exn
 transforms throw and try/catch statements into normal C functions.
diff --git a/man/frama-c.1.md b/man/frama-c.1.md
index 5b61fc0b5ecc2413ec8f9a48e0af56fabf1ce0b4..9c1876b46f6a0d221c61afd3cbfae0f188a37ea0 100644
--- a/man/frama-c.1.md
+++ b/man/frama-c.1.md
@@ -1,5 +1,5 @@
 ---
-title: 'FRAMA-C(1) 2023-02-13'
+title: 'FRAMA-C(1) 2023-05-12'
 header-includes:
 - |
   ```{=man}
@@ -16,15 +16,15 @@ header-includes:
 
   .\" DO NOT EDIT THIS FILE!
   .\" This man file has been generated from a Markdown file (frama-c.1.md)
-  .\" using pandoc 2.0 or newer. To modify this file, edit the Markdown file
-  .\" and run `make man/frama-c.1`.
+  .\" using pandoc 2.0 or newer. To modify this file, edit the Markdown file,
+  .\" run `dune build @check-man` and then `dune promote`.
   ```
 ...
 # NAME
 
-frama-c[.byte] - a static analyzer for C programs
+frama-c - a static analyzer for C programs
 
-frama-c-gui[.byte] - the graphical interface of frama-c
+frama-c-gui - the graphical interface of frama-c
 
 # SYNOPSIS
 
@@ -44,8 +44,8 @@ will provide the full list of the plugins that are currently installed.
 **frama-c-gui** is the graphical user interface of **frama-c**.
 It features the same options as the command-line version.
 
-**frama-c.byte** and **frama-c-gui.byte** are the OCaml bytecode versions
-of the command-line and graphical user interface respectively.
+**ivette** is a new, Electron-based graphical user interface for **frama-c**.
+It also features the same options as the command-line version.
 
 By default, Frama-C recognizes *.c* files as C files needing pre-processing
 and *.i* files as C files having been already pre-processed.
@@ -368,12 +368,11 @@ the Frama-C standard library. Defaults to no.
 : alias of **-print-share-path**.
 
 -print-plugin-path
-: outputs the directory where Frama-C searches its plugins (can be overridden
-by the **FRAMAC_PLUGIN** variable and the **-add-path** option).
+: outputs the directory where Frama-C searches its plugins.
 
 -print-share-path
-: outputs the directory where Frama-C stores its data (can be overridden by the
-**FRAMAC_SHARE** variable).
+: outputs the directory where Frama-C stores shareable files
+(e.g. standard library, machdeps, shared Makefiles).
 
 [-no]-remove-exn
 : transforms throw and try/catch statements into normal C functions.
diff --git a/nix/alt-ergo.nix b/nix/alt-ergo.nix
index 159534d5d6aa17a3e61d07fd862648c0d537607f..75288b5ff80bfb9a250f48bf2fd1964af1188222 100644
--- a/nix/alt-ergo.nix
+++ b/nix/alt-ergo.nix
@@ -1,50 +1,47 @@
-{ callPackage
-, fetchzip
-, lib
-, stdenv
-, ocaml
-, findlib
-, ocplib-simplex
-, psmt2-frontend
-, lablgtk
-, zarith
-, menhir
-, camlzip
-, num
-, which
-, autoreconfHook
-}:
-
-stdenv.mkDerivation rec {
-  pname = "alt-ergo";
-  version = "2.2.0-free";
-
-  src = fetchzip {
-    url = https://alt-ergo.ocamlpro.com/http/alt-ergo-free-2.2.0/alt-ergo-free-2.2.0.tar.gz;
-    sha256 = "11ffm87vsrii8nyhxhbc9gzjmqkspqv7hpjq7ll9xflll7gpnpkj";
-    stripRoot=false;
-  };
-
-  nativeBuildInputs = [
-    autoreconfHook
-    which
-  ];
+{ fetchFromGitHub, fetchpatch, lib, which, ocamlPackages }:
 
-  buildInputs = [
-    ocaml
-    findlib
-    zarith
-    ocplib-simplex
-    psmt2-frontend
-    lablgtk
-    menhir
-  ];
-
-  propagatedBuildInputs = [ camlzip num ];
+let
+  pname = "alt-ergo";
+  version = "2.4.2";
 
-  enableParallelBuilding = true;
+  configureScript = "ocaml unix.cma configure.ml";
 
-  configureFlags = [ "--enable-verbose-make" ];
+  src = fetchFromGitHub {
+    owner = "OCamlPro";
+    repo = pname;
+    rev = "refs/tags/${version}";
+    hash = "sha256-8pJ/1UAbheQaLFs5Uubmmf5D0oFJiPxF6e2WTZgRyAc=";
+  };
+in
+
+let alt-ergo-lib = ocamlPackages.buildDunePackage rec {
+  pname = "alt-ergo-lib";
+  inherit version src configureScript;
+  configureFlags = [ pname ];
+  nativeBuildInputs = [ which ];
+  buildInputs = with ocamlPackages; [ dune-configurator ];
+  propagatedBuildInputs = with ocamlPackages; [ num ocplib-simplex seq stdlib-shims zarith ];
+  preBuild = ''
+    substituteInPlace src/lib/util/version.ml --replace 'version="dev"' 'version="${version}"'
+  '';
+}; in
+
+let alt-ergo-parsers = ocamlPackages.buildDunePackage rec {
+  pname = "alt-ergo-parsers";
+  inherit version src configureScript;
+  configureFlags = [ pname ];
+  nativeBuildInputs = [ which ocamlPackages.menhir ];
+  propagatedBuildInputs = [ alt-ergo-lib ] ++ (with ocamlPackages; [ camlzip psmt2-frontend ]);
+}; in
+
+ocamlPackages.buildDunePackage {
+
+  inherit pname version src configureScript;
+
+  configureFlags = [ pname ];
+
+  nativeBuildInputs = [ which ocamlPackages.menhir ];
+  buildInputs = [ alt-ergo-parsers ocamlPackages.cmdliner ];
 
   meta = {
     description = "High-performance theorem prover and SMT solver";
diff --git a/nix/e-acsl-tests.nix b/nix/e-acsl-tests.nix
index 79c82e91a45bce3690396b3a3883d6e4d01aa832..03e5cf1998b039f38b3b1e524252b0ea288ea66a 100644
--- a/nix/e-acsl-tests.nix
+++ b/nix/e-acsl-tests.nix
@@ -1,9 +1,12 @@
-{ mk_tests } :
+{ mk_tests, config } :
+
+let e-acsl-tests = "e-acsl-tests" + (if config == "" then "" else "-" + config); in
+let ptests = "ptests_config" + (if config == "" then "" else "_" + config) ; in
+let tests = " @src/plugins/e-acsl/tests/" + ptests ; in
 
 mk_tests {
-  tests-name = "e-acsl-tests";
+  tests-name = e-acsl-tests ;
   tests-command = ''
     dune exec -- frama-c-ptests -never-disabled tests src/plugins/e-acsl/tests
-    dune build -j1 --display short @src/plugins/e-acsl/tests/ptests
-  '';
+    dune build -j1 --display short'' + tests + "\n" ;
 }
diff --git a/nix/frama-c.nix b/nix/frama-c.nix
index e24625d7c510383a88c556da57c1a6c6c50078ac..34beab7c25ad1b93e0890ec9831a9b19430a5d17 100644
--- a/nix/frama-c.nix
+++ b/nix/frama-c.nix
@@ -16,6 +16,7 @@
 , dune_3
 , dune-configurator
 , dune-site
+, fpath
 , gcc9
 , graphviz
 , lablgtk3
@@ -29,11 +30,14 @@
 , ocamlgraph_gtk
 , ocp-indent
 , ppx_deriving
+, ppx_deriving_yaml
 , ppx_deriving_yojson
 , ppx_import
+, unionFind
 , yojson
 , which
 , why3
+, yaml
 , zarith
 , zmq
 # Frama-C extra (other targets do not reconfigure)
@@ -71,6 +75,7 @@ stdenvNoCC.mkDerivation rec {
     dune-configurator
     dune-site
     findlib
+    fpath
     gcc9
     graphviz
     lablgtk3
@@ -84,11 +89,14 @@ stdenvNoCC.mkDerivation rec {
     ocamlgraph_gtk
     ocp-indent
     ppx_deriving
+    ppx_deriving_yaml
     ppx_deriving_yojson
     ppx_import
+    unionFind
     yojson
     which
     why3
+    yaml
     zarith
     zmq
     # For other CI targets
diff --git a/nix/internal-tests.nix b/nix/internal-tests.nix
index 1e144928c107a3fbffa355008c6e4057d5f29a29..34cf7a9b1e03adc0108942bad1ecc85fcd762175 100644
--- a/nix/internal-tests.nix
+++ b/nix/internal-tests.nix
@@ -30,11 +30,14 @@
 , ocamlgraph
 , ocp-indent
 , ppx_deriving
+, ppx_deriving_yaml
 , ppx_deriving_yojson
 , ppx_import
+, unionFind
 , yojson
 , which
 , why3
+, yaml
 , zarith
 , zmq
 # Frama-C tests
@@ -87,10 +90,13 @@ stdenvNoCC.mkDerivation rec {
     ocamlgraph
     ocp-indent
     ppx_deriving
+    ppx_deriving_yaml
     ppx_deriving_yojson
     ppx_import
+    unionFind
     yojson
     which
+    yaml
     why3
     zarith
     zmq
diff --git a/nix/internal-tests.sh b/nix/internal-tests.sh
index 40617ea4ebbf35e21bb2f92746681141632c3239..d9dab79d7ebef11709bf75bc93a641518d4e7435 100755
--- a/nix/internal-tests.sh
+++ b/nix/internal-tests.sh
@@ -51,9 +51,6 @@ get_matching_branch () {
   fi
 }
 
-#         fc-dir     nix-dir
-fc_dir="$(dirname "$(dirname "$(readlink -f "$0")")")"
-
 git_current_branch="$(git branch --show-current)"
 : "${git_current_branch:=${CI_COMMIT_BRANCH:-}}"
 echo "currently on branch $git_current_branch"
@@ -62,17 +59,18 @@ temporary="$(mktemp -d)"
 callsite="$(pwd)"
 
 cleanup () {
-  cd $callsite
+  cd "$callsite"
   if [[ -n $temporary ]];
-  then rm -rf $temporary
+  then rm -rf "$temporary"
   fi
   git worktree prune
 }
 
 trap cleanup EXIT
 
-git worktree add $temporary $(git rev-parse HEAD)
-cd $temporary
+git worktree add "$temporary" "$(git rev-parse HEAD)"
+cd "$temporary"
+./nix/wp-cache.nix.sh
 
 declare -A plugins=( )
 
diff --git a/nix/lint.nix b/nix/lint.nix
deleted file mode 100644
index 6f79ef2ff81350c5d295e72f36ac5ed7fc57b125..0000000000000000000000000000000000000000
--- a/nix/lint.nix
+++ /dev/null
@@ -1,41 +0,0 @@
-# TODO:
-# - enable lint E-ACSL C files
-# - enable check-headers
-
-{ lib
-, stdenv
-, bc
-# , clang_10
-, frama-c
-# , headache
-, ocp-indent
-} :
-
-stdenv.mkDerivation rec {
-  pname = "lint";
-  version = frama-c.version;
-  slang = frama-c.slang;
-
-  src = frama-c.src;
-
-  nativeBuildInputs = frama-c.nativeBuildInputs;
-
-  buildInputs = frama-c.buildInputs ++ [
-    bc
-    # headache
-    ocp-indent
-    # clang_10
-  ];
-
-  preConfigure = frama-c.preConfigure;
-
-  buildPhase = ''
-    make lint
-    make stats-lint
-    # STRICT_HEADERS=yes make check-headers
-  '';
-
-  installPhase = ''
-    touch $out
-  '';
-}
diff --git a/nix/menhirLib.nix b/nix/menhirLib.nix
deleted file mode 100644
index 34d8e09e0e5f19ad499f5779cb6c7f4a03d92b34..0000000000000000000000000000000000000000
--- a/nix/menhirLib.nix
+++ /dev/null
@@ -1,27 +0,0 @@
-{ lib, fetchFromGitLab, buildDunePackage }:
-
-buildDunePackage rec {
-  pname = "menhirLib";
-  version = "20211128";
-
-  src = fetchFromGitLab {
-    domain = "gitlab.inria.fr";
-    owner = "fpottier";
-    repo = "menhir";
-    rev = version;
-    sha256 = "0j7ba5z7rwf85zi56fd3zfp7dvhr6xlj9amambxx57szys6dzz1g";
-  };
-
-  meta = with lib; {
-    homepage = "http://pauillac.inria.fr/~fpottier/menhir/";
-    description = "Runtime support library for parsers generated by Menhir";
-    longDescription = ''
-      Menhir is a LR(1) parser generator for the Objective Caml programming
-      language.  That is, Menhir compiles LR(1) grammar specifications down
-      to OCaml code.  Menhir was designed and implemented by François Pottier
-      and Yann Régis-Gianas.
-    '';
-    license = with licenses; [ lgpl2Only ];
-    maintainers = with maintainers; [ vbgl ];
-  };
-}
diff --git a/nix/pkgs.nix b/nix/pkgs.nix
index eb2500b7752a118ac93120fde67ea16b9bee2db7..8626523577646a6e5dc34237700cfa2a2ab4dde4 100644
--- a/nix/pkgs.nix
+++ b/nix/pkgs.nix
@@ -5,10 +5,10 @@ let
     alt-ergo = oself.callPackage ./alt-ergo.nix {};
     camlp5 = oself.callPackage ./camlp5.nix {};
     headache = oself.callPackage ./headache.nix {};
-    menhirLib = oself.callPackage ./menhirLib.nix {};
     mlmpfr = oself.callPackage ./mlmpfr.nix {};
-    psmt2-frontend = oself.callPackage ./psmt2-frontend.nix {};
     why3 = oself.callPackage ./why3.nix {};
+    yaml = oself.callPackage ./yaml.nix {};
+    ppx_deriving_yaml = oself.callPackage ./ppx_deriving_yaml.nix {};
 
     # Helpers
     mk_tests = oself.callPackage ./mk_tests.nix {};
@@ -26,11 +26,11 @@ let
     frama-c = oself.callPackage ./frama-c.nix {};
     frama-c-hdrck = oself.callPackage ./frama-c-hdrck.nix {};
     frama-c-lint = oself.callPackage ./frama-c-lint.nix {};
-    lint = oself.callPackage ./lint.nix {};
 
     # Tests
     default-config-tests = oself.callPackage ./default-config-tests.nix {};
-    e-acsl-tests = oself.callPackage ./e-acsl-tests.nix {};
+    e-acsl-tests = oself.callPackage ./e-acsl-tests.nix { config = ""; };
+    e-acsl-dev-tests = oself.callPackage ./e-acsl-tests.nix { config = "dev"; };
     eva-default-tests = oself.callPackage ./eva-tests.nix { config = ""; };
     eva-apron-tests = oself.callPackage ./eva-tests.nix { config = "apron" ; };
     eva-bitwise-tests = oself.callPackage ./eva-tests.nix { config = "bitwise" ; };
diff --git a/nix/plugins-tests.nix b/nix/plugins-tests.nix
index cbbeb33d9d2fb3eb6dc8438d4cc9d0e746720061..a500d6d0ce11b44a18ed1f1690bd1ae250eb011a 100644
--- a/nix/plugins-tests.nix
+++ b/nix/plugins-tests.nix
@@ -17,6 +17,7 @@ mk_tests {
       @tests/scope/ptests \
       @tests/sparecode/ptests \
       @src/plugins/aorai/tests/ptests \
+      @src/plugins/alias/tests/ptests \
       @src/plugins/dive/tests/ptests \
       @src/plugins/instantiate/tests/ptests \
       @src/plugins/loop_analysis/tests/ptests \
diff --git a/nix/ppx_deriving_yaml.nix b/nix/ppx_deriving_yaml.nix
new file mode 100644
index 0000000000000000000000000000000000000000..44b6e980ae69201b348aad19bba59a2b4b905e85
--- /dev/null
+++ b/nix/ppx_deriving_yaml.nix
@@ -0,0 +1,27 @@
+{ lib, buildDunePackage, fetchurl, ppxlib, alcotest, mdx
+, ppx_deriving, yaml
+}:
+
+buildDunePackage rec {
+  pname = "ppx_deriving_yaml";
+  version = "0.2.1";
+
+  minimalOCamlVersion = "4.08";
+
+  src = fetchurl {
+    url = "https://github.com/patricoferris/ppx_deriving_yaml/releases/download/v${version}/ppx_deriving_yaml-${version}.tbz";
+    sha256 = "sha256-3vmay8UY7d3j96VOQ+D3oYEotzVls91F51ebXWQ/9SQ=";
+  };
+
+  propagatedBuildInputs = [ ppxlib ppx_deriving yaml ];
+
+  doCheck = true;
+  checkInputs = [ alcotest mdx ];
+
+  meta = {
+    description = "A YAML codec generator for OCaml";
+    homepage = "https://github.com/patricoferris/ppx_deriving_yaml";
+    license = lib.licenses.isc;
+    maintainers = [ ];
+  };
+}
diff --git a/nix/psmt2-frontend.nix b/nix/psmt2-frontend.nix
deleted file mode 100644
index 98836906d462ecce7f597e8e99df178b5c97fbe4..0000000000000000000000000000000000000000
--- a/nix/psmt2-frontend.nix
+++ /dev/null
@@ -1,48 +0,0 @@
-{ callPackage
-, fetchFromGitHub
-, lib
-, stdenv
-, ocaml
-, findlib
-, menhir
-, autoreconfHook
-, which
-}:
-
-stdenv.mkDerivation rec {
-  pname = "psmt2-frontend";
-  version = "0.1";
-
-  src = fetchFromGitHub {
-    owner = "Coquera";
-    repo = pname;
-    rev = version;
-    sha256 = "0k7jlsbkdyg7hafmvynp0ik8xk7mfr00wz27vxn4ncnmp20yz4vn";
-  };
-
-  nativeBuildInputs = [
-    autoreconfHook
-    which
-  ];
-
-  buildInputs = [
-    ocaml
-    findlib
-    menhir
-  ];
-
-  enableParallelBuilding = true;
-
-  configureFlags = [ "--enable-verbose-make" ];
-
-  createFindlibDestdir = true;
-
-  installFlags = "LIBDIR=$(OCAMLFIND_DESTDIR)";
-
-  meta = {
-    description = "A simple parser and type-checker for polomorphic extension of the SMT-LIB 2 language";
-    license = lib.licenses.asl20;
-    maintainers = [ lib.maintainers.vbgl ];
-    inherit (src.meta) homepage;
-  };
-}
diff --git a/nix/yaml.nix b/nix/yaml.nix
new file mode 100644
index 0000000000000000000000000000000000000000..bc8c7af164efc3768c615212b47da43ef5c8cfd5
--- /dev/null
+++ b/nix/yaml.nix
@@ -0,0 +1,32 @@
+{ lib, fetchurl, buildDunePackage
+, dune-configurator
+, bos, ctypes, fmt, logs
+, mdx, alcotest, crowbar, junit_alcotest, ezjsonm
+}:
+
+buildDunePackage rec {
+  pname = "yaml";
+  version = "3.0.1";
+
+  src = fetchurl {
+    url = "https://github.com/avsm/ocaml-yaml/releases/download/v${version}/yaml-${version}.tbz";
+    sha256 = "ku0bpClVmhS2tF4XDzSCGReR+ZrFGJpfIGEuFb+99pU=";
+  };
+
+  minimalOCamlVersion = "4.05.0";
+
+  buildInputs = [ dune-configurator ];
+  propagatedBuildInputs = [ bos ctypes ];
+
+  doCheck = true;
+  nativeCheckInputs = [ mdx.bin ];
+  checkInputs = [ fmt logs alcotest crowbar junit_alcotest ezjsonm ];
+
+  meta = {
+    description = "Parse and generate YAML 1.1 files";
+    homepage = "https://github.com/avsm/ocaml-yaml";
+    license = lib.licenses.isc;
+    maintainers = [ lib.maintainers.vbgl ];
+  };
+
+}
diff --git a/opam b/opam
index f221a563d28604d800206a45629726462bb97aff..1483c4466ca49ad7bafddc56f46be8f6ac65b27e 100644
--- a/opam
+++ b/opam
@@ -1,7 +1,7 @@
 opam-version: "2.0"
 name: "frama-c"
 synopsis: "Platform dedicated to the analysis of source code written in C"
-version: "26.1+dev"
+version: "27.0+dev"
 description:"""
 Frama-C gathers several analysis techniques in a single collaborative
 framework, based on analyzers (called "plug-ins") that can build upon the
@@ -17,7 +17,7 @@ Thanks to this approach, Frama-C provides sophisticated tools, including:
 These plug-ins communicate between each other via the Frama-C API
 and via ACSL (ANSI/ISO C Specification Language) properties.
 """
-maintainer: "francois.bobot@cea.fr"
+maintainer: "frama-ci-bot@frama-c.com"
 authors: [
   "Michele Alberti"
   "Thibaud Antignac"
@@ -40,6 +40,7 @@ authors: [
   "Philippe Herrmann"
   "Maxime Jacquemin"
   "Florent Kirchner"
+  "Alexander Kogtenkov"
   "Tristan Le Gall"
   "Jean-Christophe Léchenet"
   "Matthieu Lemerre"
@@ -60,6 +61,7 @@ authors: [
   "Armand Puccetti"
   "Félix Ridoux"
   "Virgile Robles"
+  "Jan Rochel"
   "Muriel Roger"
   "Julien Signoles"
   "Nicolas Stouls"
@@ -69,7 +71,7 @@ authors: [
 homepage: "https://frama-c.com/"
 license: "LGPL-2.1-only"
 dev-repo: "git+https://git.frama-c.com/pub/frama-c.git"
-doc: "http://frama-c.com/download/user-manual-26.1-Iron.pdf"
+doc: "http://frama-c.com/download/user-manual-27.0-Cobalt.pdf"
 bug-reports: "https://git.frama-c.com/pub/frama-c/issues"
 tags: [
   "deductive"
@@ -119,15 +121,17 @@ depends: [
   "conf-time" { with-test }
   "menhir" { >= "20181006" & build }
   "ocaml" { >= "4.11.1" }
-  "ocamlfind" # needed beyond build stage, used by -load-module
   "ocamlgraph" { >= "1.8.8" }
+  "unionFind" { >= "20220107" }
   "why3" { >= "1.6.0" }
+  "yaml" { >= "3.0.0" }
   "yojson" {>= "1.6.0" & (>= "2.0.1" | !with-test)}
   "zarith" { >= "1.5" }
 
   # PPXs
   "ppx_deriving"
   "ppx_deriving_yojson"
+  "ppx_deriving_yaml" { >= "0.2.0" }
   "ppx_import"
 
   # GTK3 for non-macos only
diff --git a/reference-configuration.md b/reference-configuration.md
index 37e05fd560a14445ac2d844221436547f69d2e84..a42c129d996338d181509daec2e1e9a241980e1d 100644
--- a/reference-configuration.md
+++ b/reference-configuration.md
@@ -4,15 +4,20 @@ compiling Frama-C+dev.
 - OCaml 4.13.1
 - alt-ergo-free.2.2.0 (for wp, optional)
 - apron.v0.9.13 (for eva, optional)
-- dune.3.4.1
-- dune-site.3.4.1
+- dune.3.5.0
+- dune-configurator.3.5.0
+- dune-site.3.5.0
 - lablgtk3.3.1.2
 - lablgtk3-sourceview3.3.1.2
+- menhir.20211128
 - mlmpfr.4.1.0+bugfix2 (for eva, optional)
 - ocamlfind.1.9.5
 - ocamlgraph.2.0.0
+- ocp-indent.1.8.1 (for linting, optional)
+- ppx_deriving_yaml.0.2.1
 - ppx_deriving_yojson.3.7.0
 - ppx_import.1.10.0
+- unionFind.20220122
 - why3.1.6.0
 - yojson.2.0.2
 - zarith.1.12
diff --git a/releases/27.0.md b/releases/27.0.md
new file mode 100644
index 0000000000000000000000000000000000000000..f650a45758482e749082bcab405bed4ba5158804
--- /dev/null
+++ b/releases/27.0.md
@@ -0,0 +1,27 @@
+# Kernel
+- Supports C11 `_Generic`
+- New machdep mechanism, based on YAML files
+- New script for generating machdeps from a C11 compiler
+
+# Aoraï
+- Supports specification about floating-point variables.
+
+# Eva
+- The octagon domain can now infer relations between any lvalues of integer or
+  pointer types.
+- Fixes the bitwise domain on big-endian architectures.
+
+# WP
+- Why3 version bumped to 1.6.0.
+- New options for controlling goal automatic splitting
+- Default timeout is now 2s
+
+# GTK GUI
+- Removed GTK2 support
+
+# Ivette
+- The Eva table can show the values of function parameters, the logical status
+  of ACSL predicates, and the values of C lvalues in these predicates.
+  It also shows the status of uninitialized and escaping variables.
+- Information about C types are shown in the Inspector.
+- Many bug fixes and user experience improvements.
diff --git a/share/analysis-scripts/clone.sh b/share/analysis-scripts/clone.sh
index 1633382be282b2561c9ca593f090920a65f9efe5..1c5abe563fd6ec5f8796bdfa8c49e7a882dc343f 100755
--- a/share/analysis-scripts/clone.sh
+++ b/share/analysis-scripts/clone.sh
@@ -94,10 +94,8 @@ if [ ! -e "$target_path/build/bin/frama-c" ]
 then
     (
         cd "$target_path";
-        autoconf -f --warnings=none;
-        ./configure --quiet --prefix=$(pwd)/build > /dev/null;
-        make -j > /dev/null;
-        make install > /dev/null;
+        make -j --quiet > /dev/null;
+        make install PREFIX=$(pwd)/build > /dev/null;
     )
 fi
 
diff --git a/share/analysis-scripts/epilogue.mk b/share/analysis-scripts/epilogue.mk
index 359a8fbf766bf381e3ed8a46b8498d0f79d5b620..7a2a542ee40ae718c6016deac7249efa49eca5b8 100644
--- a/share/analysis-scripts/epilogue.mk
+++ b/share/analysis-scripts/epilogue.mk
@@ -29,6 +29,7 @@ eva: $(TARGETS)
 parse: $(TARGETS:%.eva=%.parse)
 # Opening one GUI for each target is cumbersome; we open only the first target
 gui: $(firstword $(TARGETS)).gui
+ivette: $(firstword $(TARGETS)).ivette
 
 # Default target
 all: eva
diff --git a/share/analysis-scripts/summary.py b/share/analysis-scripts/summary.py
index 6aa1ed705db3e72b6f8c15fa9ef4dee7d027435e..20e5fdeb0ce2022b5506c22226419026c3f99603 100755
--- a/share/analysis-scripts/summary.py
+++ b/share/analysis-scripts/summary.py
@@ -126,7 +126,6 @@ def smart_rename(target):
     target = re.sub("main\.eva$", "", target)
     target = re.sub("\.eva$", "", target)
     target = re.sub("\.frama-c/", "", target)
-    target = re.sub("qds/frama-c", "qds", target)
     return target
 
 
diff --git a/share/dune b/share/dune
index b086bb6380a1d256b252d1517de32548a1871a3e..77f771002d1b2e413dd411f13512b51fbf62f5b9 100644
--- a/share/dune
+++ b/share/dune
@@ -133,8 +133,6 @@
 (libc/__fc_inet.h as libc/__fc_inet.h)
 (libc/__fc_integer.h as libc/__fc_integer.h)
 (libc/__fc_libc.h as libc/__fc_libc.h)
-(libc/__fc_machdep.h as libc/__fc_machdep.h)
-(libc/__fc_machdep_linux_shared.h as libc/__fc_machdep_linux_shared.h)
 (libc/__fc_runtime.c as libc/__fc_runtime.c)
 (libc/__fc_select.h as libc/__fc_select.h)
 (libc/__fc_string_axiomatic.h as libc/__fc_string_axiomatic.h)
@@ -326,3 +324,64 @@
 (analysis-scripts/template.mk as lib/analysis-scripts/template.mk)
 
 ))
+
+; machdeps
+(install
+ (package frama-c)
+ (section share)
+ (files
+  (machdeps/machdep_avr_8.yaml as share/machdeps/machdep_avr_8.yaml)
+  (machdeps/machdep_avr_16.yaml as share/machdeps/machdep_avr_16.yaml)
+  (machdeps/machdep_x86_16.yaml as share/machdeps/machdep_x86_16.yaml)
+  (machdeps/machdep_x86_32.yaml as share/machdeps/machdep_x86_32.yaml)
+  (machdeps/machdep_x86_64.yaml as share/machdeps/machdep_x86_64.yaml)
+  (machdeps/machdep_gcc_x86_16.yaml as share/machdeps/machdep_gcc_x86_16.yaml)
+  (machdeps/machdep_gcc_x86_32.yaml as share/machdeps/machdep_gcc_x86_32.yaml)
+  (machdeps/machdep_gcc_x86_64.yaml as share/machdeps/machdep_gcc_x86_64.yaml)
+  (machdeps/machdep_msvc_x86_64.yaml as share/machdeps/machdep_msvc_x86_64.yaml)
+  (machdeps/machdep_ppc_32.yaml as share/machdeps/machdep_ppc_32.yaml))
+)
+
+; machdep generation script
+(install
+ (package frama-c)
+ (section libexec)
+ (files
+  (machdeps/make_machdep/make_machdep.py as lib/make_machdep/make_machdep.py))
+)
+
+; machdep generation auxiliary files
+(install
+ (package frama-c)
+ (section lib)
+ (files
+  (machdeps/make_machdep/alignof_aligned.c as lib/make_machdep/alignof_aligned.c)
+  (machdeps/make_machdep/alignof_double.c as lib/make_machdep/alignof_double.c)
+  (machdeps/make_machdep/alignof_float.c as lib/make_machdep/alignof_float.c)
+  (machdeps/make_machdep/alignof_fun.c as lib/make_machdep/alignof_fun.c)
+  (machdeps/make_machdep/alignof_int.c as lib/make_machdep/alignof_int.c)
+  (machdeps/make_machdep/alignof_long.c as lib/make_machdep/alignof_long.c)
+  (machdeps/make_machdep/alignof_longdouble.c as lib/make_machdep/alignof_longdouble.c)
+  (machdeps/make_machdep/alignof_longlong.c as lib/make_machdep/alignof_longlong.c)
+  (machdeps/make_machdep/alignof_ptr.c as lib/make_machdep/alignof_ptr.c)
+  (machdeps/make_machdep/alignof_short.c as lib/make_machdep/alignof_short.c)
+  (machdeps/make_machdep/alignof_str.c as lib/make_machdep/alignof_str.c)
+  (machdeps/make_machdep/char_is_unsigned.c as lib/make_machdep/char_is_unsigned.c)
+  (machdeps/make_machdep/const_string_literals.c as lib/make_machdep/const_string_literals.c)
+  (machdeps/make_machdep/has__builtin_va_list.c as lib/make_machdep/has__builtin_va_list.c)
+  (machdeps/make_machdep/little_endian.c as lib/make_machdep/little_endian.c)
+  (machdeps/make_machdep/ptrdiff_t.c as lib/make_machdep/ptrdiff_t.c)
+  (machdeps/make_machdep/sizeof_double.c as lib/make_machdep/sizeof_double.c)
+  (machdeps/make_machdep/sizeof_float.c as lib/make_machdep/sizeof_float.c)
+  (machdeps/make_machdep/sizeof_fun.c as lib/make_machdep/sizeof_fun.c)
+  (machdeps/make_machdep/sizeof_int.c as lib/make_machdep/sizeof_int.c)
+  (machdeps/make_machdep/sizeof_long.c as lib/make_machdep/sizeof_long.c)
+  (machdeps/make_machdep/sizeof_longdouble.c as lib/make_machdep/sizeof_longdouble.c)
+  (machdeps/make_machdep/sizeof_longlong.c as lib/make_machdep/sizeof_longlong.c)
+  (machdeps/make_machdep/sizeof_ptr.c as lib/make_machdep/sizeof_ptr.c)
+  (machdeps/make_machdep/sizeof_short.c as lib/make_machdep/sizeof_short.c)
+  (machdeps/make_machdep/sizeof_void.c as lib/make_machdep/sizeof_void.c)
+  (machdeps/make_machdep/size_t.c as lib/make_machdep/size_t.c)
+  (machdeps/make_machdep/wchar_t.c as lib/make_machdep/wchar_t.c)
+  (machdeps/make_machdep/make_machdep_common.h as lib/make_machdep/make_machdep_common.h)
+))
diff --git a/share/libc/__fc_define_sigset_t.h b/share/libc/__fc_define_sigset_t.h
index b5718423a3cebd450cc8c989b7b60b679697e789..30f99f6f804ea9d320d2aa3e1378608b79fa35c9 100644
--- a/share/libc/__fc_define_sigset_t.h
+++ b/share/libc/__fc_define_sigset_t.h
@@ -32,4 +32,3 @@ typedef unsigned long sigset_t;
 __END_DECLS
 __POP_FC_STDLIB
 #endif
-
diff --git a/share/libc/__fc_machdep_linux_shared.h b/share/libc/__fc_machdep_linux_shared.h
index ac883d753c55b1c14b78296b0cabeb1577379135..3b0e48bc84dfbd98b0b4fb611e86d8f78445d073 100644
--- a/share/libc/__fc_machdep_linux_shared.h
+++ b/share/libc/__fc_machdep_linux_shared.h
@@ -117,9 +117,6 @@
 #define __FC_INTMAX_MAX 9223372036854775807LL
 #define __FC_UINTMAX_MAX 18446744073709551615ULL
 
-// Linux usually defines wchar_t as a signed int, but this is not required
-#define __WCHAR_T int
-
 /* stdio.h */
 #define __FC_BUFSIZ 8192
 #define __FC_EOF (-1)
diff --git a/share/libc/__fc_machdep.h b/share/libc/__fc_machdep_old.c
similarity index 99%
rename from share/libc/__fc_machdep.h
rename to share/libc/__fc_machdep_old.c
index 14061cd4decadc773f9aed17f40ee7b2915b2a33..f2ae398c843a010cd0dbd1f2bfdd3c00b260c673 100644
--- a/share/libc/__fc_machdep.h
+++ b/share/libc/__fc_machdep_old.c
@@ -38,6 +38,7 @@
 #define __CHAR_BIT 8
 #define __PTRDIFF_T int
 #define __SIZE_T unsigned int
+#define __WCHAR_T long
 #define __FC_INT_MIN (-2147483647 - 1)
 #define __FC_INT_MAX 2147483647
 #define __FC_UINT_MAX 4294967295U
@@ -130,6 +131,7 @@
 #define __CHAR_BIT 8
 #define __PTRDIFF_T long
 #define __SIZE_T unsigned long
+#define __WCHAR_T int
 #define __FC_INT_MIN (-2147483647 - 1)
 #define __FC_INT_MAX 2147483647
 #define __FC_UINT_MAX 4294967295U
@@ -231,6 +233,7 @@
 #define __CHAR_BIT 8
 #define __PTRDIFF_T long
 #define __SIZE_T unsigned int
+#define __WCHAR_T int
 #define __FC_INT_MIN (-32768)
 #define __FC_INT_MAX 32767
 #define __FC_UINT_MAX 65535U
@@ -335,6 +338,7 @@
 #define __CHAR_BIT 8
 #define __PTRDIFF_T int
 #define __SIZE_T unsigned int
+#define __WCHAR_T int
 #define __FC_INT_MIN (-2147483647 - 1)
 #define __FC_INT_MAX 2147483647
 #define __FC_UINT_MAX 4294967295U
diff --git a/share/libc/errno.h b/share/libc/errno.h
index ea398ffc8f14ed127dfc5bd7389a7415a3fef62b..2fa3792a89d6b39414b4610f2d3aaffbdf140bfc 100644
--- a/share/libc/errno.h
+++ b/share/libc/errno.h
@@ -117,6 +117,7 @@ __PUSH_FC_STDLIB
 #define ENOTCONN __FC_ENOTCONN
 #define ENOTDIR __FC_ENOTDIR
 #define ENOTEMPTY __FC_ENOTEMPTY
+#define ENOTRECOVERABLE __FC_ENOTRECOVERABLE
 #define ENOTSOCK __FC_ENOTSOCK
 #define ENOTSUP __FC_ENOTSUP
 #define ENOTTY __FC_ENOTTY
@@ -124,6 +125,7 @@ __PUSH_FC_STDLIB
 #define ENXIO __FC_ENXIO
 #define EOPNOTSUPP __FC_EOPNOTSUPP
 #define EOVERFLOW __FC_EOVERFLOW
+#define EOWNER_DEAD __FC_EOWNER_DEAD
 #define EPERM __FC_EPERM
 #define EPFNOSUPPORT __FC_EPFNOSUPPORT
 #define EPIPE __FC_EPIPE
diff --git a/share/libc/inttypes.h b/share/libc/inttypes.h
index 1d685c0780b45fdeae13cb8d5af1619ecd911f08..1c64e01cff56a4abce9c0cfd9a8a7389113037a2 100644
--- a/share/libc/inttypes.h
+++ b/share/libc/inttypes.h
@@ -39,15 +39,15 @@ __PUSH_FC_STDLIB
 # define PRId32		__PRI32_PREFIX "d"
 # define PRId64		__PRI64_PREFIX "d"
 
-# define PRIdLEAST8	__PRI8_PREFIX "d"
-# define PRIdLEAST16	__PRI16_PREFIX "d"
-# define PRIdLEAST32	__PRI32_PREFIX "d"
-# define PRIdLEAST64	__PRI64_PREFIX "d"
+# define PRIdLEAST8	__PRI_LEAST8_PREFIX "d"
+# define PRIdLEAST16	__PRI_LEAST16_PREFIX "d"
+# define PRIdLEAST32	__PRI_LEAST32_PREFIX "d"
+# define PRIdLEAST64	__PRI_LEAST64_PREFIX "d"
 
-# define PRIdFAST8	__PRI8_PREFIX "d"
-# define PRIdFAST16	__PRIFAST16_PREFIX "d"
-# define PRIdFAST32	__PRI32_PREFIX "d"
-# define PRIdFAST64	__PRI64_PREFIX "d"
+# define PRIdFAST8	__PRI_FAST8_PREFIX "d"
+# define PRIdFAST16	__PRI_FAST16_PREFIX "d"
+# define PRIdFAST32	__PRI_FAST32_PREFIX "d"
+# define PRIdFAST64	__PRI_FAST64_PREFIX "d"
 
 
 # define PRIi8		__PRI8_PREFIX "i"
@@ -55,15 +55,15 @@ __PUSH_FC_STDLIB
 # define PRIi32		__PRI32_PREFIX "i"
 # define PRIi64		__PRI64_PREFIX "i"
 
-# define PRIiLEAST8	__PRI8_PREFIX "i"
-# define PRIiLEAST16	__PRI16_PREFIX "i"
-# define PRIiLEAST32	__PRI32_PREFIX "i"
-# define PRIiLEAST64	__PRI64_PREFIX "i"
+# define PRIiLEAST8	__PRI_LEAST8_PREFIX "i"
+# define PRIiLEAST16	__PRI_LEAST16_PREFIX "i"
+# define PRIiLEAST32	__PRI_LEAST32_PREFIX "i"
+# define PRIiLEAST64	__PRI_LEAST64_PREFIX "i"
 
-# define PRIiFAST8	__PRI8_PREFIX "i"
-# define PRIiFAST16	__PRIFAST16_PREFIX "i"
-# define PRIiFAST32	__PRI32_PREFIX "i"
-# define PRIiFAST64	__PRI64_PREFIX "i"
+# define PRIiFAST8	__PRI_FAST8_PREFIX "i"
+# define PRIiFAST16	__PRI_FAST16_PREFIX "i"
+# define PRIiFAST32	__PRI_FAST32_PREFIX "i"
+# define PRIiFAST64	__PRI_FAST64_PREFIX "i"
 
 /* Octal notation.  */
 # define PRIo8		__PRI8_PREFIX "o"
@@ -71,15 +71,15 @@ __PUSH_FC_STDLIB
 # define PRIo32		__PRI32_PREFIX "o"
 # define PRIo64		__PRI64_PREFIX "o"
 
-# define PRIoLEAST8	__PRI8_PREFIX "o"
-# define PRIoLEAST16	__PRI16_PREFIX "o"
-# define PRIoLEAST32	__PRI32_PREFIX "o"
-# define PRIoLEAST64	__PRI64_PREFIX "o"
+# define PRIoLEAST8	__PRI_LEAST8_PREFIX "o"
+# define PRIoLEAST16	__PRI_LEAST16_PREFIX "o"
+# define PRIoLEAST32	__PRI_LEAST32_PREFIX "o"
+# define PRIoLEAST64	__PRI_LEAST64_PREFIX "o"
 
-# define PRIoFAST8	__PRI8_PREFIX "o"
-# define PRIoFAST16	__PRIFAST16_PREFIX "o"
-# define PRIoFAST32	__PRI32_PREFIX "o"
- # define PRIoFAST64	__PRI64_PREFIX "o"
+# define PRIoFAST8	__PRI_FAST8_PREFIX "o"
+# define PRIoFAST16	__PRI_FAST16_PREFIX "o"
+# define PRIoFAST32	__PRI_FAST32_PREFIX "o"
+ # define PRIoFAST64	__PRI_FAST64_PREFIX "o"
 
 /* Unsigned integers.  */
 # define PRIu8		__PRI8_PREFIX "u"
@@ -87,15 +87,15 @@ __PUSH_FC_STDLIB
 # define PRIu32		__PRI32_PREFIX "u"
 # define PRIu64		__PRI64_PREFIX "u"
 
-# define PRIuLEAST8	__PRI8_PREFIX "u"
-# define PRIuLEAST16	__PRI16_PREFIX "u"
-# define PRIuLEAST32	__PRI32_PREFIX "u"
-# define PRIuLEAST64	__PRI64_PREFIX "u"
+# define PRIuLEAST8	__PRI_LEAST8_PREFIX "u"
+# define PRIuLEAST16	__PRI_LEAST16_PREFIX "u"
+# define PRIuLEAST32	__PRI_LEAST32_PREFIX "u"
+# define PRIuLEAST64	__PRI_LEAST64_PREFIX "u"
 
-# define PRIuFAST8	__PRI8_PREFIX "u"
-# define PRIuFAST16	__PRIFAST16_PREFIX "u"
-# define PRIuFAST32	__PRI32_PREFIX "u"
-# define PRIuFAST64	__PRI64_PREFIX "u"
+# define PRIuFAST8	__PRI_FAST8_PREFIX "u"
+# define PRIuFAST16	__PRI_FAST16_PREFIX "u"
+# define PRIuFAST32	__PRI_FAST32_PREFIX "u"
+# define PRIuFAST64	__PRI_FAST64_PREFIX "u"
 
 /* lowercase hexadecimal notation.  */
 # define PRIx8		__PRI8_PREFIX "x"
@@ -103,15 +103,15 @@ __PUSH_FC_STDLIB
 # define PRIx32		__PRI32_PREFIX "x"
 # define PRIx64		__PRI64_PREFIX "x"
 
-# define PRIxLEAST8	__PRI8_PREFIX "x"
-# define PRIxLEAST16	__PRI16_PREFIX "x"
-# define PRIxLEAST32	__PRI32_PREFIX "x"
-# define PRIxLEAST64	__PRI64_PREFIX "x"
+# define PRIxLEAST8	__PRI_LEAST8_PREFIX "x"
+# define PRIxLEAST16	__PRI_LEAST16_PREFIX "x"
+# define PRIxLEAST32	__PRI_LEAST32_PREFIX "x"
+# define PRIxLEAST64	__PRI_LEAST64_PREFIX "x"
 
-# define PRIxFAST8	__PRI8_PREFIX "x"
-# define PRIxFAST16	__PRIFAST16_PREFIX "x"
-# define PRIxFAST32	__PRI32_PREFIX "x"
-# define PRIxFAST64	__PRI64_PREFIX "x"
+# define PRIxFAST8	__PRI_FAST8_PREFIX "x"
+# define PRIxFAST16	__PRI_FAST16_PREFIX "x"
+# define PRIxFAST32	__PRI_FAST32_PREFIX "x"
+# define PRIxFAST64	__PRI_FAST64_PREFIX "x"
 
 /* UPPERCASE hexadecimal notation.  */
 # define PRIX8		__PRI8_PREFIX "X"
@@ -119,15 +119,15 @@ __PUSH_FC_STDLIB
 # define PRIX32		__PRI32_PREFIX "X"
 # define PRIX64		__PRI64_PREFIX "X"
 
-# define PRIXLEAST8	__PRI8_PREFIX "X"
-# define PRIXLEAST16	__PRI16_PREFIX "X"
-# define PRIXLEAST32	__PRI32_PREFIX "X"
-# define PRIXLEAST64	__PRI64_PREFIX "X"
+# define PRIXLEAST8	__PRI_LEAST8_PREFIX "X"
+# define PRIXLEAST16	__PRI_LEAST16_PREFIX "X"
+# define PRIXLEAST32	__PRI_LEAST32_PREFIX "X"
+# define PRIXLEAST64	__PRI_LEAST64_PREFIX "X"
 
-# define PRIXFAST8	__PRI8_PREFIX "X"
-# define PRIXFAST16	__PRIFAST16_PREFIX "X"
-# define PRIXFAST32	__PRI32_PREFIX "X"
-# define PRIXFAST64	__PRI64_PREFIX "X"
+# define PRIXFAST8	__PRI_FAST8_PREFIX "X"
+# define PRIXFAST16	__PRI_FAST16_PREFIX "X"
+# define PRIXFAST32	__PRI_FAST32_PREFIX "X"
+# define PRIXFAST64	__PRI_FAST64_PREFIX "X"
 
 
 /* Macros for printing `intmax_t' and `uintmax_t'.  */
@@ -155,15 +155,15 @@ __PUSH_FC_STDLIB
 # define SCNd32		__PRI32_PREFIX "d"
 # define SCNd64		__PRI64_PREFIX "d"
 
-# define SCNdLEAST8	__PRI8_PREFIX "d"
-# define SCNdLEAST16	__PRI16_PREFIX "d"
-# define SCNdLEAST32	__PRI32_PREFIX "d"
-# define SCNdLEAST64	__PRI64_PREFIX "d"
+# define SCNdLEAST8	__PRI_LEAST8_PREFIX "d"
+# define SCNdLEAST16	__PRI_LEAST16_PREFIX "d"
+# define SCNdLEAST32	__PRI_LEAST32_PREFIX "d"
+# define SCNdLEAST64	__PRI_LEAST64_PREFIX "d"
 
-# define SCNdFAST8	__PRI8_PREFIX "d"
-# define SCNdFAST16	__PRIFAST16_PREFIX "d"
-# define SCNdFAST32	__PRI32_PREFIX "d"
-# define SCNdFAST64	__PRI64_PREFIX "d"
+# define SCNdFAST8	__PRI_FAST8_PREFIX "d"
+# define SCNdFAST16	__PRI_FAST16_PREFIX "d"
+# define SCNdFAST32	__PRI_FAST32_PREFIX "d"
+# define SCNdFAST64	__PRI_FAST64_PREFIX "d"
 
 /* Signed decimal notation.  */
 # define SCNi8		__PRI8_PREFIX "i"
@@ -171,15 +171,15 @@ __PUSH_FC_STDLIB
 # define SCNi32		__PRI32_PREFIX "i"
 # define SCNi64		__PRI64_PREFIX "i"
 
-# define SCNiLEAST8	__PRI8_PREFIX "i"
-# define SCNiLEAST16	__PRI16_PREFIX "i"
-# define SCNiLEAST32	__PRI32_PREFIX "i"
-# define SCNiLEAST64	__PRI64_PREFIX "i"
+# define SCNiLEAST8	__PRI_LEAST8_PREFIX "i"
+# define SCNiLEAST16	__PRI_LEAST16_PREFIX "i"
+# define SCNiLEAST32	__PRI_LEAST32_PREFIX "i"
+# define SCNiLEAST64	__PRI_LEAST64_PREFIX "i"
 
-# define SCNiFAST8	__PRI8_PREFIX "i"
-# define SCNiFAST16	__PRIFAST16_PREFIX "i"
-# define SCNiFAST32	__PRI32_PREFIX "i"
-# define SCNiFAST64	__PRI64_PREFIX "i"
+# define SCNiFAST8	__PRI_FAST8_PREFIX "i"
+# define SCNiFAST16	__PRI_FAST16_PREFIX "i"
+# define SCNiFAST32	__PRI_FAST32_PREFIX "i"
+# define SCNiFAST64	__PRI_FAST64_PREFIX "i"
 
 /* Unsigned decimal notation.  */
 # define SCNu8		__PRI8_PREFIX "u"
@@ -187,15 +187,15 @@ __PUSH_FC_STDLIB
 # define SCNu32		__PRI32_PREFIX "u"
 # define SCNu64		__PRI64_PREFIX "u"
 
-# define SCNuLEAST8	__PRI8_PREFIX "u"
-# define SCNuLEAST16	__PRI16_PREFIX "u"
-# define SCNuLEAST32	__PRI32_PREFIX "u"
-# define SCNuLEAST64	__PRI64_PREFIX "u"
+# define SCNuLEAST8	__PRI_LEAST8_PREFIX "u"
+# define SCNuLEAST16	__PRI_LEAST16_PREFIX "u"
+# define SCNuLEAST32	__PRI_LEAST32_PREFIX "u"
+# define SCNuLEAST64	__PRI_LEAST64_PREFIX "u"
 
-# define SCNuFAST8	__PRI8_PREFIX "u"
-# define SCNuFAST16	__PRIFAST16_PREFIX "u"
-# define SCNuFAST32	__PRI32_PREFIX "u"
-# define SCNuFAST64	__PRI64_PREFIX "u"
+# define SCNuFAST8	__PRI_FAST8_PREFIX "u"
+# define SCNuFAST16	__PRI_FAST16_PREFIX "u"
+# define SCNuFAST32	__PRI_FAST32_PREFIX "u"
+# define SCNuFAST64	__PRI_FAST64_PREFIX "u"
 
 /* Octal notation.  */
 # define SCNo8		__PRI8_PREFIX "o"
@@ -203,15 +203,15 @@ __PUSH_FC_STDLIB
 # define SCNo32		__PRI32_PREFIX "o"
 # define SCNo64		__PRI64_PREFIX "o"
 
-# define SCNoLEAST8	__PRI8_PREFIX "o"
-# define SCNoLEAST16	__PRI16_PREFIX "o"
-# define SCNoLEAST32	__PRI32_PREFIX "o"
-# define SCNoLEAST64	__PRI64_PREFIX "o"
+# define SCNoLEAST8	__PRI_LEAST8_PREFIX "o"
+# define SCNoLEAST16	__PRI_LEAST16_PREFIX "o"
+# define SCNoLEAST32	__PRI_LEAST32_PREFIX "o"
+# define SCNoLEAST64	__PRI_LEAST64_PREFIX "o"
 
-# define SCNoFAST8	__PRI8_PREFIX "o"
-# define SCNoFAST16	__PRIFAST16_PREFIX "o"
-# define SCNoFAST32	__PRI32_PREFIX "o"
-# define SCNoFAST64	__PRI64_PREFIX "o"
+# define SCNoFAST8	__PRI_FAST8_PREFIX "o"
+# define SCNoFAST16	__PRI_FAST16_PREFIX "o"
+# define SCNoFAST32	__PRI_FAST32_PREFIX "o"
+# define SCNoFAST64	__PRI_FAST64_PREFIX "o"
 
 /* Hexadecimal notation.  */
 # define SCNx8		__PRI8_PREFIX "x"
@@ -219,15 +219,15 @@ __PUSH_FC_STDLIB
 # define SCNx32		__PRI32_PREFIX "x"
 # define SCNx64		__PRI64_PREFIX "x"
 
-# define SCNxLEAST8	__PRI8_PREFIX "x"
-# define SCNxLEAST16	__PRI16_PREFIX "x"
-# define SCNxLEAST32	__PRI32_PREFIX "x"
-# define SCNxLEAST64	__PRI64_PREFIX "x"
+# define SCNxLEAST8	__PRI_LEAST8_PREFIX "x"
+# define SCNxLEAST16	__PRI_LEAST16_PREFIX "x"
+# define SCNxLEAST32	__PRI_LEAST32_PREFIX "x"
+# define SCNxLEAST64	__PRI_LEAST64_PREFIX "x"
 
-# define SCNxFAST8	__PRI8_PREFIX "x"
-# define SCNxFAST16	__PRIFAST16_PREFIX "x"
-# define SCNxFAST32	__PRI32_PREFIX "x"
-# define SCNxFAST64	__PRI64_PREFIX "x"
+# define SCNxFAST8	__PRI_FAST8_PREFIX "x"
+# define SCNxFAST16	__PRI_FAST16_PREFIX "x"
+# define SCNxFAST32	__PRI_FAST32_PREFIX "x"
+# define SCNxFAST64	__PRI_FAST64_PREFIX "x"
 
 
 /* Macros for scanning `intmax_t' and `uintmax_t'.  */
@@ -289,4 +289,3 @@ __END_DECLS
 
 __POP_FC_STDLIB
 #endif
-
diff --git a/share/libc/limits.h b/share/libc/limits.h
index 40e674b2b6d78b2d22cd2f7bac416809e8fba3a3..1e78408515458227a89bc497e13e09409fbc9327 100644
--- a/share/libc/limits.h
+++ b/share/libc/limits.h
@@ -76,30 +76,9 @@
 /* Maximum value an `unsigned long long int' can hold.  (Minimum is 0.)  */
 #   define ULLONG_MAX	__FC_ULLONG_MAX
 
-/* Maximum number of bytes in a pathname, including the terminating
-   null character. (Minimum is 256.) */
-#define PATH_MAX  __FC_PATH_MAX
-
-/* Maximum length of a host name (not including the terminating null)
-   as returned from the gethostname() function.
-   Note: Mac OS does not define this constant. */
-#define HOST_NAME_MAX __FC_HOST_NAME_MAX
-
-/* Maximum length of a terminal device name. */
-#define TTY_NAME_MAX __FC_TTY_NAME_MAX
-
-/* Maximum length of argument to the exec functions including environment data.
-   Minimum Acceptable Value: {_POSIX_ARG_MAX} (4096 in POSIX.1-2008)
-   "... the total space used to store the environment and the arguments to the
-    process is limited to {ARG_MAX} bytes."
- */
-#define ARG_MAX 4096
-
-// POSIX; used by <sys/uio.h>.
-// Must be >= _XOPEN_IOV_MAX, which is 16.
-// 1024 is the value used by some Linux implementations.
-#define IOV_MAX 1024
+// POSIX-specific definitions
 
+/*** Most restrictive values for the constants below, as mandated by POSIX */
 
 // Maximum Values
 
@@ -166,4 +145,82 @@
 #define NL_TEXTMAX _POSIX2_LINE_MAX
 #define NZERO 20
 
+/*** POSIX constants. Frama-C usually takes Linux' values by default, but
+     it can be overloaded by passing e.g. `-cpp-extra-args="-D__FC_XXXX=nnnn"`
+     on Frama-C's command line. A value of -1 will deactivate the macro (all of
+     them are optional).
+*/
+#define STR(S) # S
+#define expand(macro) STR(macro)
+
+/* Maximum number of bytes in a pathname, including the terminating
+   null character. (Minimum is 256.) */
+#ifdef __FC_PATH_MAX
+#  if __FC_PATH_MAX >= 0
+      _Static_assert(__FC_PATH_MAX >=_POSIX_PATH_MAX, "__FC_PATH_MAX is too small (" expand(__FC_PATH_MAX) "): minimal value is " expand( _POSIX_PATH_MAX));
+#      define PATH_MAX __FC_PATH_MAX
+#  else
+#    undef PATH_MAX
+#  endif
+#else
+#  define PATH_MAX  4096
+#endif
+
+/* Maximum length of a host name (not including the terminating null)
+   as returned from the gethostname() function.
+   Note: Mac OS does not define this constant, and Linux use a strictly smaller
+   one than what POSIX mandate
+*/
+#ifdef __FC_HOST_NAME_MAX
+#  if __FC_HOST_NAME_MAX >= 0
+     // _Static_assert(__FC_HOST_NAME_MAX >=_POSIX_HOST_NAME_MAX, "__FC_HOST_NAME_MAX is too small (" expand(__FC_HOST_NAME_MAX) "): minimal value is " expand(_POSIX_HOST_NAME_MAX));
+#    define HOST_NAME_MAX __FC_HOST_NAME_MAX
+#  else
+#    undef HOST_NAME_MAX
+#  endif
+#else
+#  define HOST_NAME_MAX 255
+#endif
+
+/* Maximum length of a terminal device name. */
+#ifdef __FC_TTY_NAME_MAX
+#  if __FC_TTY_NAME_MAX >= 0
+     _Static_assert(__FC_HOST_NAME_MAX >=_POSIX_TTY_NAME_MAX, "__FC_TTY_NAME_MAX is too small (" expand(__FC_TTY_NAME_MAX) "): minimal value is " expand(_POSIX_TTY_NAME_MAX));
+#    define TTY_NAME_MAX __FC_TTY_NAME_MAX
+#  else
+#    undef TTY_NAME_MAX
+#  endif
+#else
+#  define TTY_NAME_MAX 9
+#endif
+
+/* Maximum length of argument to the exec functions including environment data.
+   Minimum Acceptable Value: {_POSIX_ARG_MAX} (4096 in POSIX.1-2008)
+   "... the total space used to store the environment and the arguments to the
+    process is limited to {ARG_MAX} bytes."
+ */
+#ifdef __FC_ARG_MAX
+#  if __FC_ARG_MAX >= 0
+     _Static_assert(__FC_ARG_MAX >=_POSIX_ARG_MAX, "__FC_ARG_MAX is too small (" expand(__FC_ARG_MAX) "): minimal value is " expand(__POSIX_ARG_MAX));
+#    define ARG_MAX __FC_ARG_MAX
+#  else
+#    undef ARG_MAX
+#  endif
+#else
+#  define ARG_MAX 4096
+#endif
+
+// POSIX; used by <sys/uio.h>.
+// Must be >= _XOPEN_IOV_MAX, which is 16.
+#ifdef __FC_IOV_MAX
+#  if __FC_IOV_MAX >= 0
+     _Static_assert(__FC_IOV_MAX >=_XOPEN_IOV_MAX, "__FC_IOV_MAX is too small (" expand(__FC_IOV_MAX) "): minimal value is " expand(_XOPEN_IOV_MAX));
+#    define IOV_MAX __FC_IOV_MAX
+#  else
+#    undef IOV_MAX
+#  endif
+#else
+#  define IOV_MAX 255
+#endif
+
 #endif
diff --git a/share/libc/signal.h b/share/libc/signal.h
index 126a96f1f5eb0c79b8be42f718c9cdd4057f7cf1..30851947103312e43d4a0adf40dfc50484c68c82 100644
--- a/share/libc/signal.h
+++ b/share/libc/signal.h
@@ -35,9 +35,8 @@ __PUSH_FC_STDLIB
 
 __BEGIN_DECLS
 
-/* TODO: put sig_atomic_t in machdep */
 #ifndef __sig_atomic_t_defined
-typedef volatile int sig_atomic_t;
+typedef volatile __FC_SIG_ATOMIC_T sig_atomic_t;
 #define __sig_atomic_t_defined
 #endif
 
@@ -103,9 +102,16 @@ extern void __fc_sig_err(int);
 #define SIGRTMIN 32
 #define SIGRTMAX 64
 
+/* Non-standard macros (depending on the OS, the name has an underscore or not)
+   supposed to be the number of distinct signals that may be raised.
+   Upcoming POSIX standard seems to allow for a NSIG_MAX macro in limits.h that
+   would have roughly the same usage as NSIG (NSIG_MAX would be the maximal value
+   that a signal can have, i.e. NSIG-1 if we start at 0 and don't leave holes. If
+   this ever becomes supported, we might use this macro instead
+*/
+#ifdef __FC_NSIG
 #define NSIG __FC_NSIG
-#ifdef __FC__NSIG
-#define _NSIG __FC__NSIG
+#define _NSIG __FC_NSIG
 #endif
 
 #define SA_NOCLDSTOP	0x00000001
diff --git a/share/libc/stdint.h b/share/libc/stdint.h
index 09169deced239d98936f085195b16650aed1ba28..839a90e3dc1132e9b5b6a947ef2c27164faf0ec4 100644
--- a/share/libc/stdint.h
+++ b/share/libc/stdint.h
@@ -96,8 +96,8 @@ typedef __UINTPTR_T uintptr_t;
 #endif
 
 /* ISO C: 7.18.1.5 */
-typedef __INT_MAX_T intmax_t;
-typedef __UINT_MAX_T uintmax_t;
+typedef __INTMAX_T intmax_t;
+typedef __UINTMAX_T uintmax_t;
 
 /* ISO C: 7.18.2.1 */
 #define INT8_MIN (-128)
@@ -147,9 +147,9 @@ typedef __UINT_MAX_T uintmax_t;
 /* ISO C: 7.18.2.4 - Done directly with definition of corresponding types. */
 
 /* ISO C: 7.18.2.5 */
-#define INTMAX_MIN __FC_INTMAX_MIN
-#define INTMAX_MAX __FC_INTMAX_MAX
-#define UINTMAX_MAX __FC_UINTMAX_MAX
+#define INTMAX_MIN __INTMAX_MIN
+#define INTMAX_MAX __INTMAX_MAX
+#define UINTMAX_MAX __UINTMAX_MAX
 
 /* ISO C: 7.18.3 */
 
diff --git a/share/libc/stdio.h b/share/libc/stdio.h
index eb9282338d5d02a068833c6b89765bf6cac52ff3..736bcfa6f6f4e52131b4d68b2a431f809a707fc2 100644
--- a/share/libc/stdio.h
+++ b/share/libc/stdio.h
@@ -621,7 +621,5 @@ int asprintf(char **strp, const char *fmt, ...);
 
 __END_DECLS
 
-#define IOV_MAX 1024
-
 __POP_FC_STDLIB
 #endif
diff --git a/share/libc/sys/socket.h b/share/libc/sys/socket.h
index 5885125caafe53c8d88ffdb47095ed3a97f7d89a..f96e482a5e5a6ada267a7e4d7f40605abbf8503c 100644
--- a/share/libc/sys/socket.h
+++ b/share/libc/sys/socket.h
@@ -25,7 +25,7 @@
 #include "../features.h"
 __PUSH_FC_STDLIB
 __BEGIN_DECLS
-#include "../__fc_machdep.h"
+#include "__fc_machdep.h"
 
 #include "../errno.h"
 
diff --git a/share/libc/sys/types.h b/share/libc/sys/types.h
index 73ac60e89245e728374ec8684164b1d3b5ff3c3a..38ae7d90f8b15a832c296f94cc8f0607f4f09dee 100644
--- a/share/libc/sys/types.h
+++ b/share/libc/sys/types.h
@@ -26,7 +26,7 @@
 __PUSH_FC_STDLIB
 __BEGIN_DECLS
 
-#include "../__fc_machdep.h"
+#include "__fc_machdep.h"
 #include "../__fc_define_id_t.h"
 #include "../__fc_define_pid_t.h"
 #include "../__fc_define_size_t.h"
diff --git a/share/libc/unistd.h b/share/libc/unistd.h
index b6e8f0b54628de43c8fe181b61ec43f8e1837c44..a5ba5bf7da343d2590a12be9a56d68c547ecd89e 100644
--- a/share/libc/unistd.h
+++ b/share/libc/unistd.h
@@ -38,6 +38,13 @@ __PUSH_FC_STDLIB
 #include "__fc_define_intptr_t.h"
 #include "__fc_define_fds.h"
 #include "limits.h"
+
+#ifndef __FC_POSIX_VERSION
+#error "unistd.h should only be included with a POSIX machdep"
+#endif
+
+#define _POSIX_VERSION __FC_POSIX_VERSION
+
 __BEGIN_DECLS
 
 extern volatile int Frama_C_entropy_source;
diff --git a/share/machdeps/.machdep_gcc_x86_16.yaml.validated b/share/machdeps/.machdep_gcc_x86_16.yaml.validated
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/share/machdeps/.machdep_msvc_x86_64.yaml.validated b/share/machdeps/.machdep_msvc_x86_64.yaml.validated
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/dev/update_api_doc.sh b/share/machdeps/Makefile
old mode 100755
new mode 100644
similarity index 61%
rename from dev/update_api_doc.sh
rename to share/machdeps/Makefile
index 879e0d50410e98b64cf220c67bef3c2ef0567ee3..f2fc15fd2e11603d2a235e5e64f4aa128eed77e8
--- a/dev/update_api_doc.sh
+++ b/share/machdeps/Makefile
@@ -1,4 +1,3 @@
-#!/bin/sh
 ##########################################################################
 #                                                                        #
 #  This file is part of Frama-C.                                         #
@@ -21,12 +20,29 @@
 #                                                                        #
 ##########################################################################
 
-next=$1
+MANUAL_MACHDEPS=machdep_gcc_x86_16.yaml machdep_msvc_x86_64.yaml
 
-if test -z "$next"; then
-  echo "Missing argument. Usage is:"
-  echo "\$ ./bin/update_api_doc.sh <NEXT>"
-  echo "See the Release Management Documentation for an example."
-else
-  find src -name '*.ml*' -exec sed -i -e "s/Frama-C+dev/${next}/gI" '{}' ';'
-fi
+update-all: machdep_*.yaml $(MANUAL_MACHDEPS:%=.%.validated)
+
+machdep_avr_8.yaml \
+machdep_avr_16.yaml \
+machdep_gcc_x86_32.yaml \
+machdep_gcc_x86_64.yaml \
+machdep_ppc_32.yaml : \
+%.yaml: machdep-schema.yaml make_machdep/make_machdep.py make_machdep/*.c
+	@./make_machdep/make_machdep.py -i --from-file $@ --check
+
+machdep_x86_16.yaml machdep_x86_32.yaml machdep_x86_64.yaml: \
+machdep_%.yaml: machdep_gcc_%.yaml Makefile
+	@sed -e 's/sizeof_fun: .*/sizeof_fun: -1/' \
+             -e 's/sizeof_void: .*/sizeof_void: -1/' \
+             -e 's/alignof_fun: .*/alignof_fun: -1/' \
+             -e 's/compiler: .*/compiler: generic/' \
+             -e 's/machdep_name: *machdep_gcc_\([[:alnum:]]*\)/machdep_name: machdep_\1/' \
+             -e '/ *#undef __GCC.*/d' -e '/ *#define __GCC.*/d' \
+             $< > $@
+
+.%.validated: % machdep-schema.yaml
+	@echo "Checking $*"
+	@./make_machdep/make_machdep.py --from-file $* --check-only
+	@touch $@
diff --git a/share/machdeps/machdep-schema.yaml b/share/machdeps/machdep-schema.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d36c36b1ad8621056f0bf22ca56be363d85212cd
--- /dev/null
+++ b/share/machdeps/machdep-schema.yaml
@@ -0,0 +1,391 @@
+# Schema of the machine information required by Frama-C.
+
+alignof_aligned:
+
+  description: alignment of a type with 'aligned' attribute
+
+  type: integer
+
+alignof_double:
+
+  description: alignment of 'double' type
+
+  type: integer
+
+alignof_float:
+
+  description: alignment of 'float' type
+
+  type: integer
+
+alignof_fun:
+
+  description: (non-standard) alignment of a function type. Negative if unsupported
+
+  type: integer
+
+alignof_int:
+
+  description:  alignment of 'int' type
+
+  type: integer
+
+alignof_long:
+
+  description:  alignment of 'long' type
+
+  type: integer
+
+alignof_longdouble:
+
+  description:  alignment of 'long double' type
+
+  type: integer
+
+alignof_longlong:
+
+  description:  alignment of 'long long' type
+
+  type: integer
+
+alignof_ptr:
+
+  description:  alignment of 'void*' type
+
+  type: integer
+
+alignof_short:
+
+  description:  alignment of 'short' type
+
+  type: integer
+
+alignof_str:
+
+  description:  alignment of string
+
+  type: integer
+
+bufsiz:
+
+  description: value of 'BUFSIZ' macro
+
+  type: string
+
+char_is_unsigned:
+
+  description:  whether 'char' is unsigned
+
+  type: boolean
+
+compiler:
+
+  description:  compiler being used
+
+  type: string
+
+cpp_arch_flags:
+
+  description: |
+    arguments to be given to the compiler to select the corresponding
+    architecture (e.g. '-m32')
+
+  type: list
+
+  items:
+
+    - type: string
+
+custom_defs:
+  description: |
+    arbitrary text that will be reproduced verbatim in the generated
+    header
+  type: string
+
+eof:
+
+  description: value of 'EOF' macro
+
+  type: string
+
+errno:
+
+  description: all error macros defined in errno.h
+
+  type: list
+
+  items:
+
+    type: object
+    name:
+      description: macro name (lowercase)
+      type: string
+    value:
+      description: actual value
+      type: string
+
+filename_max:
+
+  description: value of 'FILENAME_MAX' macro
+
+  type: string
+
+fopen_max:
+
+  description: value of 'FOPEN_MAX' macro
+
+  type: string
+
+has__builtin_va_list:
+
+  description:  Whether '__builtin_va_list' is a known type
+
+  type: boolean
+
+host_name_max:
+
+  description: expansion of 'HOST_NAME_MAX' POSIX macro
+
+  type: string
+
+int_fast8_t:
+
+  description: definition of 'int_fast8_t'
+
+  type: string
+
+int_fast16_t:
+
+  description: definition of 'int_fast16_t'
+
+  type: string
+
+int_fast32_t:
+
+  description: definition of 'int_fast32_t'
+
+  type: string
+
+int_fast64_t:
+
+  description: definition of 'int_fast64_t'
+
+  type: string
+
+intptr_t:
+  description: definition of 'intptr_t'
+
+  type: string
+
+l_tmpnam:
+
+  description: value of 'L_tmpnam' macro
+
+  type: string
+
+little_endian:
+
+  description:  whether the architecture is little-endian
+
+  type: boolean
+
+machdep_name:
+
+  description: |
+    name of the machdep. Will be used to define a macro allowing
+    to know during preprocessing which machdep has been selected.
+
+  type: string
+
+mb_cur_max:
+
+  description: expansion of 'MB_CUR_MAX' macro
+
+  type: string
+
+nsig:
+
+  description: number of possible signals (non standard macro, empty if undefined)
+
+  type: string
+
+path_max:
+
+  description: expansion of 'PATH_MAX' POSIX macro
+
+  type: string
+
+posix_version:
+  description: |
+    value of the macro '_POSIX_VERSION'
+    leave empty for non-POSIX systems
+
+  type: string
+
+ptrdiff_t:
+
+  description:  definition of 'ptrdiff_t'
+
+  type: string
+
+rand_max:
+
+  description: expansion of 'RAND_MAX' macro
+
+  type: string
+
+sig_atomic_t:
+
+  description: representation of 'sig_atomic_t' (defined in signal.h)
+
+  type: string
+
+size_t:
+
+  description:  type of 'sizeof e'
+
+  type: string
+
+sizeof_double:
+
+  description:  size of 'double' type
+
+  type: integer
+
+sizeof_float:
+
+  description:  size of 'float' type
+
+  type: integer
+
+sizeof_fun:
+
+  description:  (non-standard) size of a function type. Negative if unsupported
+
+  type: integer
+
+sizeof_int:
+
+  description:  size of 'int' type
+
+  type: integer
+
+sizeof_long:
+
+  description:  size of 'long' type
+
+  type: integer
+
+sizeof_longdouble:
+
+  description:  size of 'long double' type
+
+  type: integer
+
+sizeof_longlong:
+
+  description:  size of 'long long' type
+
+  type: integer
+
+sizeof_ptr:
+
+  description:  size of 'void*' type
+
+  type: integer
+
+sizeof_short:
+
+  description:  size of 'short' type
+
+  type: integer
+
+sizeof_void:
+
+  description:  (non-standard) size of 'void' type. Negative if unsupported
+
+  type: integer
+
+ssize_t:
+
+  description: definition of 'ssize_t' (POSIX standard type)
+
+  type: string
+
+time_t:
+
+  description: definition of 'time_t' (in time.h)
+
+  type: string
+
+tmp_max:
+
+  description: value of 'TMP_MAX' macro
+
+  type: string
+
+tty_name_max:
+
+  description: value of 'TTY_NAME_MAX' POSIX macro
+
+  type: string
+
+uint_fast8_t:
+
+  description: definition of 'uint_fast8_t'
+
+  type: string
+
+uint_fast16_t:
+
+  description: definition of 'uint_fast16_t'
+
+  type: string
+
+uint_fast32_t:
+
+  description: definition of 'uint_fast32_t'
+
+  type: string
+
+uint_fast64_t:
+
+  description: definition of 'uint_fast64_t'
+
+  type: string
+
+uintptr_t:
+
+  description: definition of 'uintptr_t'
+
+  type: string
+
+version:
+
+  description:  information on this machdep
+
+  type: string
+
+wchar_t:
+
+  description:  definition of 'wchar_t'
+
+  type: string
+
+weof:
+
+  description: value of 'WEOF' macro
+
+  type: string
+
+wint_t:
+
+  description: definition of 'wint_t'
+
+  type: string
+
+wordsize:
+
+  description: value of "__WORDSIZE" macro
+
+  type: string
diff --git a/share/machdeps/machdep_avr_16.yaml b/share/machdeps/machdep_avr_16.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f5ee3f6c8487f9c21f3de15a75d7255d4ff617d8
--- /dev/null
+++ b/share/machdeps/machdep_avr_16.yaml
@@ -0,0 +1,759 @@
+alignof_aligned: 1
+alignof_double: 1
+alignof_float: 1
+alignof_fun: 4
+alignof_int: 1
+alignof_long: 1
+alignof_longdouble: 1
+alignof_longlong: 1
+alignof_ptr: 1
+alignof_short: 2
+alignof_str: 1
+bufsiz: '1024'
+char_is_unsigned: false
+compiler: clang
+cpp_arch_flags:
+- -target
+- avr
+- -m16
+custom_defs: |
+    #undef AVR
+    #define AVR 1
+    #undef __ATOMIC_ACQUIRE
+    #define __ATOMIC_ACQUIRE 2
+    #undef __ATOMIC_ACQ_REL
+    #define __ATOMIC_ACQ_REL 4
+    #undef __ATOMIC_CONSUME
+    #define __ATOMIC_CONSUME 1
+    #undef __ATOMIC_RELAXED
+    #define __ATOMIC_RELAXED 0
+    #undef __ATOMIC_RELEASE
+    #define __ATOMIC_RELEASE 3
+    #undef __ATOMIC_SEQ_CST
+    #define __ATOMIC_SEQ_CST 5
+    #undef __AVR
+    #define __AVR 1
+    #undef __AVR__
+    #define __AVR__ 1
+    #undef __BIGGEST_ALIGNMENT__
+    #define __BIGGEST_ALIGNMENT__ 1
+    #undef __BITINT_MAXWIDTH__
+    #define __BITINT_MAXWIDTH__ 128
+    #undef __BOOL_WIDTH__
+    #define __BOOL_WIDTH__ 8
+    #undef __BYTE_ORDER__
+    #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+    #undef __CHAR16_TYPE__
+    #define __CHAR16_TYPE__ unsigned int
+    #undef __CHAR32_TYPE__
+    #define __CHAR32_TYPE__ long unsigned int
+    #undef __CHAR_BIT__
+    #define __CHAR_BIT__ 8
+    #undef __CLANG_ATOMIC_BOOL_LOCK_FREE
+    #define __CLANG_ATOMIC_BOOL_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_CHAR16_T_LOCK_FREE
+    #define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_CHAR32_T_LOCK_FREE
+    #define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_CHAR_LOCK_FREE
+    #define __CLANG_ATOMIC_CHAR_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_INT_LOCK_FREE
+    #define __CLANG_ATOMIC_INT_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_LLONG_LOCK_FREE
+    #define __CLANG_ATOMIC_LLONG_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_LONG_LOCK_FREE
+    #define __CLANG_ATOMIC_LONG_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_POINTER_LOCK_FREE
+    #define __CLANG_ATOMIC_POINTER_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_SHORT_LOCK_FREE
+    #define __CLANG_ATOMIC_SHORT_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_WCHAR_T_LOCK_FREE
+    #define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 1
+    #undef __CONSTANT_CFSTRINGS__
+    #define __CONSTANT_CFSTRINGS__ 1
+    #undef __DBL_DECIMAL_DIG__
+    #define __DBL_DECIMAL_DIG__ 9
+    #undef __DBL_DENORM_MIN__
+    #define __DBL_DENORM_MIN__ 1.40129846e-45
+    #undef __DBL_DIG__
+    #define __DBL_DIG__ 6
+    #undef __DBL_EPSILON__
+    #define __DBL_EPSILON__ 1.19209290e-7
+    #undef __DBL_HAS_DENORM__
+    #define __DBL_HAS_DENORM__ 1
+    #undef __DBL_HAS_INFINITY__
+    #define __DBL_HAS_INFINITY__ 1
+    #undef __DBL_HAS_QUIET_NAN__
+    #define __DBL_HAS_QUIET_NAN__ 1
+    #undef __DBL_MANT_DIG__
+    #define __DBL_MANT_DIG__ 24
+    #undef __DBL_MAX_10_EXP__
+    #define __DBL_MAX_10_EXP__ 38
+    #undef __DBL_MAX_EXP__
+    #define __DBL_MAX_EXP__ 128
+    #undef __DBL_MAX__
+    #define __DBL_MAX__ 3.40282347e+38
+    #undef __DBL_MIN_10_EXP__
+    #define __DBL_MIN_10_EXP__ (-37)
+    #undef __DBL_MIN_EXP__
+    #define __DBL_MIN_EXP__ (-125)
+    #undef __DBL_MIN__
+    #define __DBL_MIN__ 1.17549435e-38
+    #undef __DECIMAL_DIG__
+    #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
+    #undef __ELF__
+    #define __ELF__ 1
+    #undef __FINITE_MATH_ONLY__
+    #define __FINITE_MATH_ONLY__ 0
+    #undef __FLT_DECIMAL_DIG__
+    #define __FLT_DECIMAL_DIG__ 9
+    #undef __FLT_DENORM_MIN__
+    #define __FLT_DENORM_MIN__ 1.40129846e-45F
+    #undef __FLT_DIG__
+    #define __FLT_DIG__ 6
+    #undef __FLT_EPSILON__
+    #define __FLT_EPSILON__ 1.19209290e-7F
+    #undef __FLT_HAS_DENORM__
+    #define __FLT_HAS_DENORM__ 1
+    #undef __FLT_HAS_INFINITY__
+    #define __FLT_HAS_INFINITY__ 1
+    #undef __FLT_HAS_QUIET_NAN__
+    #define __FLT_HAS_QUIET_NAN__ 1
+    #undef __FLT_MANT_DIG__
+    #define __FLT_MANT_DIG__ 24
+    #undef __FLT_MAX_10_EXP__
+    #define __FLT_MAX_10_EXP__ 38
+    #undef __FLT_MAX_EXP__
+    #define __FLT_MAX_EXP__ 128
+    #undef __FLT_MAX__
+    #define __FLT_MAX__ 3.40282347e+38F
+    #undef __FLT_MIN_10_EXP__
+    #define __FLT_MIN_10_EXP__ (-37)
+    #undef __FLT_MIN_EXP__
+    #define __FLT_MIN_EXP__ (-125)
+    #undef __FLT_MIN__
+    #define __FLT_MIN__ 1.17549435e-38F
+    #undef __FLT_RADIX__
+    #define __FLT_RADIX__ 2
+    #undef __GCC_ATOMIC_BOOL_LOCK_FREE
+    #define __GCC_ATOMIC_BOOL_LOCK_FREE 1
+    #undef __GCC_ATOMIC_CHAR16_T_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 1
+    #undef __GCC_ATOMIC_CHAR32_T_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 1
+    #undef __GCC_ATOMIC_CHAR_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR_LOCK_FREE 1
+    #undef __GCC_ATOMIC_INT_LOCK_FREE
+    #define __GCC_ATOMIC_INT_LOCK_FREE 1
+    #undef __GCC_ATOMIC_LLONG_LOCK_FREE
+    #define __GCC_ATOMIC_LLONG_LOCK_FREE 1
+    #undef __GCC_ATOMIC_LONG_LOCK_FREE
+    #define __GCC_ATOMIC_LONG_LOCK_FREE 1
+    #undef __GCC_ATOMIC_POINTER_LOCK_FREE
+    #define __GCC_ATOMIC_POINTER_LOCK_FREE 1
+    #undef __GCC_ATOMIC_SHORT_LOCK_FREE
+    #define __GCC_ATOMIC_SHORT_LOCK_FREE 1
+    #undef __GCC_ATOMIC_TEST_AND_SET_TRUEVAL
+    #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
+    #undef __GCC_ATOMIC_WCHAR_T_LOCK_FREE
+    #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 1
+    #undef __GNUC_MINOR__
+    #define __GNUC_MINOR__ 2
+    #undef __GNUC_PATCHLEVEL__
+    #define __GNUC_PATCHLEVEL__ 1
+    #undef __GNUC_STDC_INLINE__
+    #define __GNUC_STDC_INLINE__ 1
+    #undef __GNUC__
+    #define __GNUC__ 4
+    #undef __GXX_ABI_VERSION
+    #define __GXX_ABI_VERSION 1002
+    #undef __INT16_C_SUFFIX__
+    #define __INT16_C_SUFFIX__
+    #undef __INT16_FMTd__
+    #define __INT16_FMTd__ "d"
+    #undef __INT16_FMTi__
+    #define __INT16_FMTi__ "i"
+    #undef __INT16_MAX__
+    #define __INT16_MAX__ 32767
+    #undef __INT16_TYPE__
+    #define __INT16_TYPE__ int
+    #undef __INT32_C_SUFFIX__
+    #define __INT32_C_SUFFIX__ L
+    #undef __INT32_FMTd__
+    #define __INT32_FMTd__ "ld"
+    #undef __INT32_FMTi__
+    #define __INT32_FMTi__ "li"
+    #undef __INT32_MAX__
+    #define __INT32_MAX__ 2147483647L
+    #undef __INT32_TYPE__
+    #define __INT32_TYPE__ long int
+    #undef __INT64_C_SUFFIX__
+    #define __INT64_C_SUFFIX__ LL
+    #undef __INT64_FMTd__
+    #define __INT64_FMTd__ "lld"
+    #undef __INT64_FMTi__
+    #define __INT64_FMTi__ "lli"
+    #undef __INT64_MAX__
+    #define __INT64_MAX__ 9223372036854775807LL
+    #undef __INT64_TYPE__
+    #define __INT64_TYPE__ long long int
+    #undef __INT8_C_SUFFIX__
+    #define __INT8_C_SUFFIX__
+    #undef __INT8_FMTd__
+    #define __INT8_FMTd__ "hhd"
+    #undef __INT8_FMTi__
+    #define __INT8_FMTi__ "hhi"
+    #undef __INT8_MAX__
+    #define __INT8_MAX__ 127
+    #undef __INT8_TYPE__
+    #define __INT8_TYPE__ signed char
+    #undef __INTMAX_C_SUFFIX__
+    #define __INTMAX_C_SUFFIX__ LL
+    #undef __INTMAX_FMTd__
+    #define __INTMAX_FMTd__ "lld"
+    #undef __INTMAX_FMTi__
+    #define __INTMAX_FMTi__ "lli"
+    #undef __INTMAX_MAX__
+    #define __INTMAX_MAX__ 9223372036854775807LL
+    #undef __INTMAX_TYPE__
+    #define __INTMAX_TYPE__ long long int
+    #undef __INTMAX_WIDTH__
+    #define __INTMAX_WIDTH__ 64
+    #undef __INTPTR_FMTd__
+    #define __INTPTR_FMTd__ "d"
+    #undef __INTPTR_FMTi__
+    #define __INTPTR_FMTi__ "i"
+    #undef __INTPTR_MAX__
+    #define __INTPTR_MAX__ 32767
+    #undef __INTPTR_TYPE__
+    #define __INTPTR_TYPE__ int
+    #undef __INTPTR_WIDTH__
+    #define __INTPTR_WIDTH__ 16
+    #undef __INT_FAST16_FMTd__
+    #define __INT_FAST16_FMTd__ "d"
+    #undef __INT_FAST16_FMTi__
+    #define __INT_FAST16_FMTi__ "i"
+    #undef __INT_FAST16_MAX__
+    #define __INT_FAST16_MAX__ 32767
+    #undef __INT_FAST16_TYPE__
+    #define __INT_FAST16_TYPE__ int
+    #undef __INT_FAST16_WIDTH__
+    #define __INT_FAST16_WIDTH__ 16
+    #undef __INT_FAST32_FMTd__
+    #define __INT_FAST32_FMTd__ "ld"
+    #undef __INT_FAST32_FMTi__
+    #define __INT_FAST32_FMTi__ "li"
+    #undef __INT_FAST32_MAX__
+    #define __INT_FAST32_MAX__ 2147483647L
+    #undef __INT_FAST32_TYPE__
+    #define __INT_FAST32_TYPE__ long int
+    #undef __INT_FAST32_WIDTH__
+    #define __INT_FAST32_WIDTH__ 32
+    #undef __INT_FAST64_FMTd__
+    #define __INT_FAST64_FMTd__ "lld"
+    #undef __INT_FAST64_FMTi__
+    #define __INT_FAST64_FMTi__ "lli"
+    #undef __INT_FAST64_MAX__
+    #define __INT_FAST64_MAX__ 9223372036854775807LL
+    #undef __INT_FAST64_TYPE__
+    #define __INT_FAST64_TYPE__ long long int
+    #undef __INT_FAST64_WIDTH__
+    #define __INT_FAST64_WIDTH__ 64
+    #undef __INT_FAST8_FMTd__
+    #define __INT_FAST8_FMTd__ "hhd"
+    #undef __INT_FAST8_FMTi__
+    #define __INT_FAST8_FMTi__ "hhi"
+    #undef __INT_FAST8_MAX__
+    #define __INT_FAST8_MAX__ 127
+    #undef __INT_FAST8_TYPE__
+    #define __INT_FAST8_TYPE__ signed char
+    #undef __INT_FAST8_WIDTH__
+    #define __INT_FAST8_WIDTH__ 8
+    #undef __INT_LEAST16_FMTd__
+    #define __INT_LEAST16_FMTd__ "d"
+    #undef __INT_LEAST16_FMTi__
+    #define __INT_LEAST16_FMTi__ "i"
+    #undef __INT_LEAST16_MAX__
+    #define __INT_LEAST16_MAX__ 32767
+    #undef __INT_LEAST16_TYPE__
+    #define __INT_LEAST16_TYPE__ int
+    #undef __INT_LEAST16_WIDTH__
+    #define __INT_LEAST16_WIDTH__ 16
+    #undef __INT_LEAST32_FMTd__
+    #define __INT_LEAST32_FMTd__ "ld"
+    #undef __INT_LEAST32_FMTi__
+    #define __INT_LEAST32_FMTi__ "li"
+    #undef __INT_LEAST32_MAX__
+    #define __INT_LEAST32_MAX__ 2147483647L
+    #undef __INT_LEAST32_TYPE__
+    #define __INT_LEAST32_TYPE__ long int
+    #undef __INT_LEAST32_WIDTH__
+    #define __INT_LEAST32_WIDTH__ 32
+    #undef __INT_LEAST64_FMTd__
+    #define __INT_LEAST64_FMTd__ "lld"
+    #undef __INT_LEAST64_FMTi__
+    #define __INT_LEAST64_FMTi__ "lli"
+    #undef __INT_LEAST64_MAX__
+    #define __INT_LEAST64_MAX__ 9223372036854775807LL
+    #undef __INT_LEAST64_TYPE__
+    #define __INT_LEAST64_TYPE__ long long int
+    #undef __INT_LEAST64_WIDTH__
+    #define __INT_LEAST64_WIDTH__ 64
+    #undef __INT_LEAST8_FMTd__
+    #define __INT_LEAST8_FMTd__ "hhd"
+    #undef __INT_LEAST8_FMTi__
+    #define __INT_LEAST8_FMTi__ "hhi"
+    #undef __INT_LEAST8_MAX__
+    #define __INT_LEAST8_MAX__ 127
+    #undef __INT_LEAST8_TYPE__
+    #define __INT_LEAST8_TYPE__ signed char
+    #undef __INT_LEAST8_WIDTH__
+    #define __INT_LEAST8_WIDTH__ 8
+    #undef __INT_MAX__
+    #define __INT_MAX__ 32767
+    #undef __INT_WIDTH__
+    #define __INT_WIDTH__ 16
+    #undef __LDBL_DECIMAL_DIG__
+    #define __LDBL_DECIMAL_DIG__ 9
+    #undef __LDBL_DENORM_MIN__
+    #define __LDBL_DENORM_MIN__ 1.40129846e-45L
+    #undef __LDBL_DIG__
+    #define __LDBL_DIG__ 6
+    #undef __LDBL_EPSILON__
+    #define __LDBL_EPSILON__ 1.19209290e-7L
+    #undef __LDBL_HAS_DENORM__
+    #define __LDBL_HAS_DENORM__ 1
+    #undef __LDBL_HAS_INFINITY__
+    #define __LDBL_HAS_INFINITY__ 1
+    #undef __LDBL_HAS_QUIET_NAN__
+    #define __LDBL_HAS_QUIET_NAN__ 1
+    #undef __LDBL_MANT_DIG__
+    #define __LDBL_MANT_DIG__ 24
+    #undef __LDBL_MAX_10_EXP__
+    #define __LDBL_MAX_10_EXP__ 38
+    #undef __LDBL_MAX_EXP__
+    #define __LDBL_MAX_EXP__ 128
+    #undef __LDBL_MAX__
+    #define __LDBL_MAX__ 3.40282347e+38L
+    #undef __LDBL_MIN_10_EXP__
+    #define __LDBL_MIN_10_EXP__ (-37)
+    #undef __LDBL_MIN_EXP__
+    #define __LDBL_MIN_EXP__ (-125)
+    #undef __LDBL_MIN__
+    #define __LDBL_MIN__ 1.17549435e-38L
+    #undef __LITTLE_ENDIAN__
+    #define __LITTLE_ENDIAN__ 1
+    #undef __LLONG_WIDTH__
+    #define __LLONG_WIDTH__ 64
+    #undef __LONG_LONG_MAX__
+    #define __LONG_LONG_MAX__ 9223372036854775807LL
+    #undef __LONG_MAX__
+    #define __LONG_MAX__ 2147483647L
+    #undef __LONG_WIDTH__
+    #define __LONG_WIDTH__ 32
+    #undef __NO_INLINE__
+    #define __NO_INLINE__ 1
+    #undef __OBJC_BOOL_IS_BOOL
+    #define __OBJC_BOOL_IS_BOOL 0
+    #undef __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES
+    #define __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES 3
+    #undef __OPENCL_MEMORY_SCOPE_DEVICE
+    #define __OPENCL_MEMORY_SCOPE_DEVICE 2
+    #undef __OPENCL_MEMORY_SCOPE_SUB_GROUP
+    #define __OPENCL_MEMORY_SCOPE_SUB_GROUP 4
+    #undef __OPENCL_MEMORY_SCOPE_WORK_GROUP
+    #define __OPENCL_MEMORY_SCOPE_WORK_GROUP 1
+    #undef __OPENCL_MEMORY_SCOPE_WORK_ITEM
+    #define __OPENCL_MEMORY_SCOPE_WORK_ITEM 0
+    #undef __ORDER_BIG_ENDIAN__
+    #define __ORDER_BIG_ENDIAN__ 4321
+    #undef __ORDER_LITTLE_ENDIAN__
+    #define __ORDER_LITTLE_ENDIAN__ 1234
+    #undef __ORDER_PDP_ENDIAN__
+    #define __ORDER_PDP_ENDIAN__ 3412
+    #undef __POINTER_WIDTH__
+    #define __POINTER_WIDTH__ 16
+    #undef __PRAGMA_REDEFINE_EXTNAME
+    #define __PRAGMA_REDEFINE_EXTNAME 1
+    #undef __PTRDIFF_FMTd__
+    #define __PTRDIFF_FMTd__ "d"
+    #undef __PTRDIFF_FMTi__
+    #define __PTRDIFF_FMTi__ "i"
+    #undef __PTRDIFF_MAX__
+    #define __PTRDIFF_MAX__ 32767
+    #undef __PTRDIFF_TYPE__
+    #define __PTRDIFF_TYPE__ int
+    #undef __PTRDIFF_WIDTH__
+    #define __PTRDIFF_WIDTH__ 16
+    #undef __SCHAR_MAX__
+    #define __SCHAR_MAX__ 127
+    #undef __SHRT_MAX__
+    #define __SHRT_MAX__ 32767
+    #undef __SHRT_WIDTH__
+    #define __SHRT_WIDTH__ 16
+    #undef __SIG_ATOMIC_MAX__
+    #define __SIG_ATOMIC_MAX__ 127
+    #undef __SIG_ATOMIC_WIDTH__
+    #define __SIG_ATOMIC_WIDTH__ 8
+    #undef __SIZEOF_DOUBLE__
+    #define __SIZEOF_DOUBLE__ 4
+    #undef __SIZEOF_FLOAT__
+    #define __SIZEOF_FLOAT__ 4
+    #undef __SIZEOF_INT__
+    #define __SIZEOF_INT__ 2
+    #undef __SIZEOF_LONG_DOUBLE__
+    #define __SIZEOF_LONG_DOUBLE__ 4
+    #undef __SIZEOF_LONG_LONG__
+    #define __SIZEOF_LONG_LONG__ 8
+    #undef __SIZEOF_LONG__
+    #define __SIZEOF_LONG__ 4
+    #undef __SIZEOF_POINTER__
+    #define __SIZEOF_POINTER__ 2
+    #undef __SIZEOF_PTRDIFF_T__
+    #define __SIZEOF_PTRDIFF_T__ 2
+    #undef __SIZEOF_SHORT__
+    #define __SIZEOF_SHORT__ 2
+    #undef __SIZEOF_SIZE_T__
+    #define __SIZEOF_SIZE_T__ 2
+    #undef __SIZEOF_WCHAR_T__
+    #define __SIZEOF_WCHAR_T__ 2
+    #undef __SIZEOF_WINT_T__
+    #define __SIZEOF_WINT_T__ 2
+    #undef __SIZE_FMTX__
+    #define __SIZE_FMTX__ "X"
+    #undef __SIZE_FMTo__
+    #define __SIZE_FMTo__ "o"
+    #undef __SIZE_FMTu__
+    #define __SIZE_FMTu__ "u"
+    #undef __SIZE_FMTx__
+    #define __SIZE_FMTx__ "x"
+    #undef __SIZE_MAX__
+    #define __SIZE_MAX__ 65535U
+    #undef __SIZE_TYPE__
+    #define __SIZE_TYPE__ unsigned int
+    #undef __SIZE_WIDTH__
+    #define __SIZE_WIDTH__ 16
+    #undef __UINT16_C_SUFFIX__
+    #define __UINT16_C_SUFFIX__ U
+    #undef __UINT16_FMTX__
+    #define __UINT16_FMTX__ "X"
+    #undef __UINT16_FMTo__
+    #define __UINT16_FMTo__ "o"
+    #undef __UINT16_FMTu__
+    #define __UINT16_FMTu__ "u"
+    #undef __UINT16_FMTx__
+    #define __UINT16_FMTx__ "x"
+    #undef __UINT16_MAX__
+    #define __UINT16_MAX__ 65535U
+    #undef __UINT16_TYPE__
+    #define __UINT16_TYPE__ unsigned int
+    #undef __UINT32_C_SUFFIX__
+    #define __UINT32_C_SUFFIX__ UL
+    #undef __UINT32_FMTX__
+    #define __UINT32_FMTX__ "lX"
+    #undef __UINT32_FMTo__
+    #define __UINT32_FMTo__ "lo"
+    #undef __UINT32_FMTu__
+    #define __UINT32_FMTu__ "lu"
+    #undef __UINT32_FMTx__
+    #define __UINT32_FMTx__ "lx"
+    #undef __UINT32_MAX__
+    #define __UINT32_MAX__ 4294967295UL
+    #undef __UINT32_TYPE__
+    #define __UINT32_TYPE__ long unsigned int
+    #undef __UINT64_C_SUFFIX__
+    #define __UINT64_C_SUFFIX__ ULL
+    #undef __UINT64_FMTX__
+    #define __UINT64_FMTX__ "llX"
+    #undef __UINT64_FMTo__
+    #define __UINT64_FMTo__ "llo"
+    #undef __UINT64_FMTu__
+    #define __UINT64_FMTu__ "llu"
+    #undef __UINT64_FMTx__
+    #define __UINT64_FMTx__ "llx"
+    #undef __UINT64_MAX__
+    #define __UINT64_MAX__ 18446744073709551615ULL
+    #undef __UINT64_TYPE__
+    #define __UINT64_TYPE__ long long unsigned int
+    #undef __UINT8_C_SUFFIX__
+    #define __UINT8_C_SUFFIX__
+    #undef __UINT8_FMTX__
+    #define __UINT8_FMTX__ "hhX"
+    #undef __UINT8_FMTo__
+    #define __UINT8_FMTo__ "hho"
+    #undef __UINT8_FMTu__
+    #define __UINT8_FMTu__ "hhu"
+    #undef __UINT8_FMTx__
+    #define __UINT8_FMTx__ "hhx"
+    #undef __UINT8_MAX__
+    #define __UINT8_MAX__ 255
+    #undef __UINT8_TYPE__
+    #define __UINT8_TYPE__ unsigned char
+    #undef __UINTMAX_C_SUFFIX__
+    #define __UINTMAX_C_SUFFIX__ ULL
+    #undef __UINTMAX_FMTX__
+    #define __UINTMAX_FMTX__ "llX"
+    #undef __UINTMAX_FMTo__
+    #define __UINTMAX_FMTo__ "llo"
+    #undef __UINTMAX_FMTu__
+    #define __UINTMAX_FMTu__ "llu"
+    #undef __UINTMAX_FMTx__
+    #define __UINTMAX_FMTx__ "llx"
+    #undef __UINTMAX_MAX__
+    #define __UINTMAX_MAX__ 18446744073709551615ULL
+    #undef __UINTMAX_TYPE__
+    #define __UINTMAX_TYPE__ long long unsigned int
+    #undef __UINTMAX_WIDTH__
+    #define __UINTMAX_WIDTH__ 64
+    #undef __UINTPTR_FMTX__
+    #define __UINTPTR_FMTX__ "X"
+    #undef __UINTPTR_FMTo__
+    #define __UINTPTR_FMTo__ "o"
+    #undef __UINTPTR_FMTu__
+    #define __UINTPTR_FMTu__ "u"
+    #undef __UINTPTR_FMTx__
+    #define __UINTPTR_FMTx__ "x"
+    #undef __UINTPTR_MAX__
+    #define __UINTPTR_MAX__ 65535U
+    #undef __UINTPTR_TYPE__
+    #define __UINTPTR_TYPE__ unsigned int
+    #undef __UINTPTR_WIDTH__
+    #define __UINTPTR_WIDTH__ 16
+    #undef __UINT_FAST16_FMTX__
+    #define __UINT_FAST16_FMTX__ "X"
+    #undef __UINT_FAST16_FMTo__
+    #define __UINT_FAST16_FMTo__ "o"
+    #undef __UINT_FAST16_FMTu__
+    #define __UINT_FAST16_FMTu__ "u"
+    #undef __UINT_FAST16_FMTx__
+    #define __UINT_FAST16_FMTx__ "x"
+    #undef __UINT_FAST16_MAX__
+    #define __UINT_FAST16_MAX__ 65535U
+    #undef __UINT_FAST16_TYPE__
+    #define __UINT_FAST16_TYPE__ unsigned int
+    #undef __UINT_FAST32_FMTX__
+    #define __UINT_FAST32_FMTX__ "lX"
+    #undef __UINT_FAST32_FMTo__
+    #define __UINT_FAST32_FMTo__ "lo"
+    #undef __UINT_FAST32_FMTu__
+    #define __UINT_FAST32_FMTu__ "lu"
+    #undef __UINT_FAST32_FMTx__
+    #define __UINT_FAST32_FMTx__ "lx"
+    #undef __UINT_FAST32_MAX__
+    #define __UINT_FAST32_MAX__ 4294967295UL
+    #undef __UINT_FAST32_TYPE__
+    #define __UINT_FAST32_TYPE__ long unsigned int
+    #undef __UINT_FAST64_FMTX__
+    #define __UINT_FAST64_FMTX__ "llX"
+    #undef __UINT_FAST64_FMTo__
+    #define __UINT_FAST64_FMTo__ "llo"
+    #undef __UINT_FAST64_FMTu__
+    #define __UINT_FAST64_FMTu__ "llu"
+    #undef __UINT_FAST64_FMTx__
+    #define __UINT_FAST64_FMTx__ "llx"
+    #undef __UINT_FAST64_MAX__
+    #define __UINT_FAST64_MAX__ 18446744073709551615ULL
+    #undef __UINT_FAST64_TYPE__
+    #define __UINT_FAST64_TYPE__ long long unsigned int
+    #undef __UINT_FAST8_FMTX__
+    #define __UINT_FAST8_FMTX__ "hhX"
+    #undef __UINT_FAST8_FMTo__
+    #define __UINT_FAST8_FMTo__ "hho"
+    #undef __UINT_FAST8_FMTu__
+    #define __UINT_FAST8_FMTu__ "hhu"
+    #undef __UINT_FAST8_FMTx__
+    #define __UINT_FAST8_FMTx__ "hhx"
+    #undef __UINT_FAST8_MAX__
+    #define __UINT_FAST8_MAX__ 255
+    #undef __UINT_FAST8_TYPE__
+    #define __UINT_FAST8_TYPE__ unsigned char
+    #undef __UINT_LEAST16_FMTX__
+    #define __UINT_LEAST16_FMTX__ "X"
+    #undef __UINT_LEAST16_FMTo__
+    #define __UINT_LEAST16_FMTo__ "o"
+    #undef __UINT_LEAST16_FMTu__
+    #define __UINT_LEAST16_FMTu__ "u"
+    #undef __UINT_LEAST16_FMTx__
+    #define __UINT_LEAST16_FMTx__ "x"
+    #undef __UINT_LEAST16_MAX__
+    #define __UINT_LEAST16_MAX__ 65535U
+    #undef __UINT_LEAST16_TYPE__
+    #define __UINT_LEAST16_TYPE__ unsigned int
+    #undef __UINT_LEAST32_FMTX__
+    #define __UINT_LEAST32_FMTX__ "lX"
+    #undef __UINT_LEAST32_FMTo__
+    #define __UINT_LEAST32_FMTo__ "lo"
+    #undef __UINT_LEAST32_FMTu__
+    #define __UINT_LEAST32_FMTu__ "lu"
+    #undef __UINT_LEAST32_FMTx__
+    #define __UINT_LEAST32_FMTx__ "lx"
+    #undef __UINT_LEAST32_MAX__
+    #define __UINT_LEAST32_MAX__ 4294967295UL
+    #undef __UINT_LEAST32_TYPE__
+    #define __UINT_LEAST32_TYPE__ long unsigned int
+    #undef __UINT_LEAST64_FMTX__
+    #define __UINT_LEAST64_FMTX__ "llX"
+    #undef __UINT_LEAST64_FMTo__
+    #define __UINT_LEAST64_FMTo__ "llo"
+    #undef __UINT_LEAST64_FMTu__
+    #define __UINT_LEAST64_FMTu__ "llu"
+    #undef __UINT_LEAST64_FMTx__
+    #define __UINT_LEAST64_FMTx__ "llx"
+    #undef __UINT_LEAST64_MAX__
+    #define __UINT_LEAST64_MAX__ 18446744073709551615ULL
+    #undef __UINT_LEAST64_TYPE__
+    #define __UINT_LEAST64_TYPE__ long long unsigned int
+    #undef __UINT_LEAST8_FMTX__
+    #define __UINT_LEAST8_FMTX__ "hhX"
+    #undef __UINT_LEAST8_FMTo__
+    #define __UINT_LEAST8_FMTo__ "hho"
+    #undef __UINT_LEAST8_FMTu__
+    #define __UINT_LEAST8_FMTu__ "hhu"
+    #undef __UINT_LEAST8_FMTx__
+    #define __UINT_LEAST8_FMTx__ "hhx"
+    #undef __UINT_LEAST8_MAX__
+    #define __UINT_LEAST8_MAX__ 255
+    #undef __UINT_LEAST8_TYPE__
+    #define __UINT_LEAST8_TYPE__ unsigned char
+    #undef __USER_LABEL_PREFIX__
+    #define __USER_LABEL_PREFIX__
+    #undef __VERSION__
+    #define __VERSION__ "Clang 15.0.7"
+    #undef __WCHAR_MAX__
+    #define __WCHAR_MAX__ 32767
+    #undef __WCHAR_TYPE__
+    #define __WCHAR_TYPE__ int
+    #undef __WCHAR_WIDTH__
+    #define __WCHAR_WIDTH__ 16
+    #undef __WINT_MAX__
+    #define __WINT_MAX__ 32767
+    #undef __WINT_TYPE__
+    #define __WINT_TYPE__ int
+    #undef __WINT_WIDTH__
+    #define __WINT_WIDTH__ 16
+    #undef __clang__
+    #define __clang__ 1
+    #undef __clang_literal_encoding__
+    #define __clang_literal_encoding__ "UTF-8"
+    #undef __clang_major__
+    #define __clang_major__ 15
+    #undef __clang_minor__
+    #define __clang_minor__ 0
+    #undef __clang_patchlevel__
+    #define __clang_patchlevel__ 7
+    #undef __clang_version__
+    #define __clang_version__ "15.0.7 "
+    #undef __clang_wide_literal_encoding__
+    #define __clang_wide_literal_encoding__ "UTF-16"
+    #undef __llvm__
+    #define __llvm__ 1
+eof: (-1)
+errno:
+    e2big: ((int)(66072050 & 0xffff))
+    eacces: ((int)(66072050 & 0xffff))
+    eaddrinuse: ((int)(66072050 & 0xffff))
+    eaddrnotavail: ((int)(66072050 & 0xffff))
+    eafnosupport: ((int)(66072050 & 0xffff))
+    eagain: ((int)(66072050 & 0xffff))
+    ealready: ((int)(66072050 & 0xffff))
+    ebadf: ((int)(66072050 & 0xffff))
+    ebusy: ((int)(66072050 & 0xffff))
+    echild: ((int)(66072050 & 0xffff))
+    econnaborted: ((int)(66072050 & 0xffff))
+    econnrefused: ((int)(66072050 & 0xffff))
+    econnreset: ((int)(66072050 & 0xffff))
+    edeadlk: ((int)(66072050 & 0xffff))
+    edestaddrreq: ((int)(66072050 & 0xffff))
+    edom: '33'
+    eexist: ((int)(66072050 & 0xffff))
+    efault: ((int)(66072050 & 0xffff))
+    efbig: ((int)(66072050 & 0xffff))
+    ehostunreach: ((int)(66072050 & 0xffff))
+    eilseq: ((int)(66072050 & 0xffff))
+    einprogress: ((int)(66072050 & 0xffff))
+    eintr: ((int)(2453066 & 0x7fff))
+    einval: ((int)(66072050 & 0xffff))
+    eio: ((int)(66072050 & 0xffff))
+    eisconn: ((int)(66072050 & 0xffff))
+    eisdir: ((int)(66072050 & 0xffff))
+    eloop: ((int)(66072050 & 0xffff))
+    emfile: ((int)(66072050 & 0xffff))
+    emlink: ((int)(66072050 & 0xffff))
+    emsgsize: ((int)(66072050 & 0xffff))
+    enametoolong: ((int)(66072050 & 0xffff))
+    enetdown: ((int)(66072050 & 0xffff))
+    enetreset: ((int)(66072050 & 0xffff))
+    enetunreach: ((int)(66072050 & 0xffff))
+    enfile: ((int)(66072050 & 0xffff))
+    enobufs: ((int)(66072050 & 0xffff))
+    enodev: ((int)(66072050 & 0xffff))
+    enoent: ((int)(66072050 & 0xffff))
+    enoexec: ((int)(66072050 & 0xffff))
+    enolck: ((int)(66072050 & 0xffff))
+    enomem: ((int)(66072050 & 0xffff))
+    enomsg: ((int)(66072050 & 0xffff))
+    enoprotoopt: ((int)(66072050 & 0xffff))
+    enospc: ((int)(66072050 & 0xffff))
+    enosys: ((int)(66081697 & 0x7fff))
+    enotconn: ((int)(66072050 & 0xffff))
+    enotdir: ((int)(66072050 & 0xffff))
+    enotempty: ((int)(66072050 & 0xffff))
+    enotsock: ((int)(66072050 & 0xffff))
+    enotty: ((int)(66072050 & 0xffff))
+    enxio: ((int)(66072050 & 0xffff))
+    eopnotsupp: ((int)(66072050 & 0xffff))
+    eperm: ((int)(66072050 & 0xffff))
+    epipe: ((int)(66072050 & 0xffff))
+    eprotonosupport: ((int)(66072050 & 0xffff))
+    eprototype: ((int)(66072050 & 0xffff))
+    erange: '34'
+    erofs: ((int)(66072050 & 0xffff))
+    espipe: ((int)(66072050 & 0xffff))
+    esrch: ((int)(66072050 & 0xffff))
+    etimedout: ((int)(66072050 & 0xffff))
+    ewouldblock: ((int)(66072050 & 0xffff))
+    exdev: ((int)(66072050 & 0xffff))
+filename_max: ''
+fopen_max: ''
+has__builtin_va_list: true
+host_name_max: '64'
+int_fast16_t: int
+int_fast32_t: long
+int_fast64_t: long long
+int_fast8_t: signed char
+intptr_t: int
+l_tmpnam: ''
+little_endian: true
+machdep_name: machdep_avr_16
+mb_cur_max: ((size_t)16)
+nsig: ''
+path_max: '4096'
+posix_version: ''
+ptrdiff_t: int
+rand_max: '0x7FFF'
+sig_atomic_t: ''
+size_t: unsigned int
+sizeof_double: 4
+sizeof_float: 4
+sizeof_fun: 1
+sizeof_int: 2
+sizeof_long: 4
+sizeof_longdouble: 4
+sizeof_longlong: 8
+sizeof_ptr: 2
+sizeof_short: 2
+sizeof_void: 1
+ssize_t: ''
+time_t: unsigned long
+tmp_max: ''
+tty_name_max: '32'
+uint_fast16_t: unsigned int
+uint_fast32_t: unsigned long
+uint_fast64_t: unsigned long long
+uint_fast8_t: unsigned char
+uintptr_t: unsigned int
+version: clang version 15.0.7
+wchar_t: int
+weof: (0xffffffffu)
+wint_t: int
+wordsize: '32'
diff --git a/share/machdeps/machdep_avr_8.yaml b/share/machdeps/machdep_avr_8.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..9a9268a4d5590425281b29da80561ab9d037b8cd
--- /dev/null
+++ b/share/machdeps/machdep_avr_8.yaml
@@ -0,0 +1,758 @@
+alignof_aligned: 1
+alignof_double: 1
+alignof_float: 1
+alignof_fun: 4
+alignof_int: 1
+alignof_long: 1
+alignof_longdouble: 1
+alignof_longlong: 1
+alignof_ptr: 1
+alignof_short: 2
+alignof_str: 1
+bufsiz: '1024'
+char_is_unsigned: false
+compiler: clang
+cpp_arch_flags:
+- -target
+- avr
+custom_defs: |
+    #undef AVR
+    #define AVR 1
+    #undef __ATOMIC_ACQUIRE
+    #define __ATOMIC_ACQUIRE 2
+    #undef __ATOMIC_ACQ_REL
+    #define __ATOMIC_ACQ_REL 4
+    #undef __ATOMIC_CONSUME
+    #define __ATOMIC_CONSUME 1
+    #undef __ATOMIC_RELAXED
+    #define __ATOMIC_RELAXED 0
+    #undef __ATOMIC_RELEASE
+    #define __ATOMIC_RELEASE 3
+    #undef __ATOMIC_SEQ_CST
+    #define __ATOMIC_SEQ_CST 5
+    #undef __AVR
+    #define __AVR 1
+    #undef __AVR__
+    #define __AVR__ 1
+    #undef __BIGGEST_ALIGNMENT__
+    #define __BIGGEST_ALIGNMENT__ 1
+    #undef __BITINT_MAXWIDTH__
+    #define __BITINT_MAXWIDTH__ 128
+    #undef __BOOL_WIDTH__
+    #define __BOOL_WIDTH__ 8
+    #undef __BYTE_ORDER__
+    #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+    #undef __CHAR16_TYPE__
+    #define __CHAR16_TYPE__ unsigned int
+    #undef __CHAR32_TYPE__
+    #define __CHAR32_TYPE__ long unsigned int
+    #undef __CHAR_BIT__
+    #define __CHAR_BIT__ 8
+    #undef __CLANG_ATOMIC_BOOL_LOCK_FREE
+    #define __CLANG_ATOMIC_BOOL_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_CHAR16_T_LOCK_FREE
+    #define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_CHAR32_T_LOCK_FREE
+    #define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_CHAR_LOCK_FREE
+    #define __CLANG_ATOMIC_CHAR_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_INT_LOCK_FREE
+    #define __CLANG_ATOMIC_INT_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_LLONG_LOCK_FREE
+    #define __CLANG_ATOMIC_LLONG_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_LONG_LOCK_FREE
+    #define __CLANG_ATOMIC_LONG_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_POINTER_LOCK_FREE
+    #define __CLANG_ATOMIC_POINTER_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_SHORT_LOCK_FREE
+    #define __CLANG_ATOMIC_SHORT_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_WCHAR_T_LOCK_FREE
+    #define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 1
+    #undef __CONSTANT_CFSTRINGS__
+    #define __CONSTANT_CFSTRINGS__ 1
+    #undef __DBL_DECIMAL_DIG__
+    #define __DBL_DECIMAL_DIG__ 9
+    #undef __DBL_DENORM_MIN__
+    #define __DBL_DENORM_MIN__ 1.40129846e-45
+    #undef __DBL_DIG__
+    #define __DBL_DIG__ 6
+    #undef __DBL_EPSILON__
+    #define __DBL_EPSILON__ 1.19209290e-7
+    #undef __DBL_HAS_DENORM__
+    #define __DBL_HAS_DENORM__ 1
+    #undef __DBL_HAS_INFINITY__
+    #define __DBL_HAS_INFINITY__ 1
+    #undef __DBL_HAS_QUIET_NAN__
+    #define __DBL_HAS_QUIET_NAN__ 1
+    #undef __DBL_MANT_DIG__
+    #define __DBL_MANT_DIG__ 24
+    #undef __DBL_MAX_10_EXP__
+    #define __DBL_MAX_10_EXP__ 38
+    #undef __DBL_MAX_EXP__
+    #define __DBL_MAX_EXP__ 128
+    #undef __DBL_MAX__
+    #define __DBL_MAX__ 3.40282347e+38
+    #undef __DBL_MIN_10_EXP__
+    #define __DBL_MIN_10_EXP__ (-37)
+    #undef __DBL_MIN_EXP__
+    #define __DBL_MIN_EXP__ (-125)
+    #undef __DBL_MIN__
+    #define __DBL_MIN__ 1.17549435e-38
+    #undef __DECIMAL_DIG__
+    #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
+    #undef __ELF__
+    #define __ELF__ 1
+    #undef __FINITE_MATH_ONLY__
+    #define __FINITE_MATH_ONLY__ 0
+    #undef __FLT_DECIMAL_DIG__
+    #define __FLT_DECIMAL_DIG__ 9
+    #undef __FLT_DENORM_MIN__
+    #define __FLT_DENORM_MIN__ 1.40129846e-45F
+    #undef __FLT_DIG__
+    #define __FLT_DIG__ 6
+    #undef __FLT_EPSILON__
+    #define __FLT_EPSILON__ 1.19209290e-7F
+    #undef __FLT_HAS_DENORM__
+    #define __FLT_HAS_DENORM__ 1
+    #undef __FLT_HAS_INFINITY__
+    #define __FLT_HAS_INFINITY__ 1
+    #undef __FLT_HAS_QUIET_NAN__
+    #define __FLT_HAS_QUIET_NAN__ 1
+    #undef __FLT_MANT_DIG__
+    #define __FLT_MANT_DIG__ 24
+    #undef __FLT_MAX_10_EXP__
+    #define __FLT_MAX_10_EXP__ 38
+    #undef __FLT_MAX_EXP__
+    #define __FLT_MAX_EXP__ 128
+    #undef __FLT_MAX__
+    #define __FLT_MAX__ 3.40282347e+38F
+    #undef __FLT_MIN_10_EXP__
+    #define __FLT_MIN_10_EXP__ (-37)
+    #undef __FLT_MIN_EXP__
+    #define __FLT_MIN_EXP__ (-125)
+    #undef __FLT_MIN__
+    #define __FLT_MIN__ 1.17549435e-38F
+    #undef __FLT_RADIX__
+    #define __FLT_RADIX__ 2
+    #undef __GCC_ATOMIC_BOOL_LOCK_FREE
+    #define __GCC_ATOMIC_BOOL_LOCK_FREE 1
+    #undef __GCC_ATOMIC_CHAR16_T_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 1
+    #undef __GCC_ATOMIC_CHAR32_T_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 1
+    #undef __GCC_ATOMIC_CHAR_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR_LOCK_FREE 1
+    #undef __GCC_ATOMIC_INT_LOCK_FREE
+    #define __GCC_ATOMIC_INT_LOCK_FREE 1
+    #undef __GCC_ATOMIC_LLONG_LOCK_FREE
+    #define __GCC_ATOMIC_LLONG_LOCK_FREE 1
+    #undef __GCC_ATOMIC_LONG_LOCK_FREE
+    #define __GCC_ATOMIC_LONG_LOCK_FREE 1
+    #undef __GCC_ATOMIC_POINTER_LOCK_FREE
+    #define __GCC_ATOMIC_POINTER_LOCK_FREE 1
+    #undef __GCC_ATOMIC_SHORT_LOCK_FREE
+    #define __GCC_ATOMIC_SHORT_LOCK_FREE 1
+    #undef __GCC_ATOMIC_TEST_AND_SET_TRUEVAL
+    #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
+    #undef __GCC_ATOMIC_WCHAR_T_LOCK_FREE
+    #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 1
+    #undef __GNUC_MINOR__
+    #define __GNUC_MINOR__ 2
+    #undef __GNUC_PATCHLEVEL__
+    #define __GNUC_PATCHLEVEL__ 1
+    #undef __GNUC_STDC_INLINE__
+    #define __GNUC_STDC_INLINE__ 1
+    #undef __GNUC__
+    #define __GNUC__ 4
+    #undef __GXX_ABI_VERSION
+    #define __GXX_ABI_VERSION 1002
+    #undef __INT16_C_SUFFIX__
+    #define __INT16_C_SUFFIX__
+    #undef __INT16_FMTd__
+    #define __INT16_FMTd__ "d"
+    #undef __INT16_FMTi__
+    #define __INT16_FMTi__ "i"
+    #undef __INT16_MAX__
+    #define __INT16_MAX__ 32767
+    #undef __INT16_TYPE__
+    #define __INT16_TYPE__ int
+    #undef __INT32_C_SUFFIX__
+    #define __INT32_C_SUFFIX__ L
+    #undef __INT32_FMTd__
+    #define __INT32_FMTd__ "ld"
+    #undef __INT32_FMTi__
+    #define __INT32_FMTi__ "li"
+    #undef __INT32_MAX__
+    #define __INT32_MAX__ 2147483647L
+    #undef __INT32_TYPE__
+    #define __INT32_TYPE__ long int
+    #undef __INT64_C_SUFFIX__
+    #define __INT64_C_SUFFIX__ LL
+    #undef __INT64_FMTd__
+    #define __INT64_FMTd__ "lld"
+    #undef __INT64_FMTi__
+    #define __INT64_FMTi__ "lli"
+    #undef __INT64_MAX__
+    #define __INT64_MAX__ 9223372036854775807LL
+    #undef __INT64_TYPE__
+    #define __INT64_TYPE__ long long int
+    #undef __INT8_C_SUFFIX__
+    #define __INT8_C_SUFFIX__
+    #undef __INT8_FMTd__
+    #define __INT8_FMTd__ "hhd"
+    #undef __INT8_FMTi__
+    #define __INT8_FMTi__ "hhi"
+    #undef __INT8_MAX__
+    #define __INT8_MAX__ 127
+    #undef __INT8_TYPE__
+    #define __INT8_TYPE__ signed char
+    #undef __INTMAX_C_SUFFIX__
+    #define __INTMAX_C_SUFFIX__ LL
+    #undef __INTMAX_FMTd__
+    #define __INTMAX_FMTd__ "lld"
+    #undef __INTMAX_FMTi__
+    #define __INTMAX_FMTi__ "lli"
+    #undef __INTMAX_MAX__
+    #define __INTMAX_MAX__ 9223372036854775807LL
+    #undef __INTMAX_TYPE__
+    #define __INTMAX_TYPE__ long long int
+    #undef __INTMAX_WIDTH__
+    #define __INTMAX_WIDTH__ 64
+    #undef __INTPTR_FMTd__
+    #define __INTPTR_FMTd__ "d"
+    #undef __INTPTR_FMTi__
+    #define __INTPTR_FMTi__ "i"
+    #undef __INTPTR_MAX__
+    #define __INTPTR_MAX__ 32767
+    #undef __INTPTR_TYPE__
+    #define __INTPTR_TYPE__ int
+    #undef __INTPTR_WIDTH__
+    #define __INTPTR_WIDTH__ 16
+    #undef __INT_FAST16_FMTd__
+    #define __INT_FAST16_FMTd__ "d"
+    #undef __INT_FAST16_FMTi__
+    #define __INT_FAST16_FMTi__ "i"
+    #undef __INT_FAST16_MAX__
+    #define __INT_FAST16_MAX__ 32767
+    #undef __INT_FAST16_TYPE__
+    #define __INT_FAST16_TYPE__ int
+    #undef __INT_FAST16_WIDTH__
+    #define __INT_FAST16_WIDTH__ 16
+    #undef __INT_FAST32_FMTd__
+    #define __INT_FAST32_FMTd__ "ld"
+    #undef __INT_FAST32_FMTi__
+    #define __INT_FAST32_FMTi__ "li"
+    #undef __INT_FAST32_MAX__
+    #define __INT_FAST32_MAX__ 2147483647L
+    #undef __INT_FAST32_TYPE__
+    #define __INT_FAST32_TYPE__ long int
+    #undef __INT_FAST32_WIDTH__
+    #define __INT_FAST32_WIDTH__ 32
+    #undef __INT_FAST64_FMTd__
+    #define __INT_FAST64_FMTd__ "lld"
+    #undef __INT_FAST64_FMTi__
+    #define __INT_FAST64_FMTi__ "lli"
+    #undef __INT_FAST64_MAX__
+    #define __INT_FAST64_MAX__ 9223372036854775807LL
+    #undef __INT_FAST64_TYPE__
+    #define __INT_FAST64_TYPE__ long long int
+    #undef __INT_FAST64_WIDTH__
+    #define __INT_FAST64_WIDTH__ 64
+    #undef __INT_FAST8_FMTd__
+    #define __INT_FAST8_FMTd__ "hhd"
+    #undef __INT_FAST8_FMTi__
+    #define __INT_FAST8_FMTi__ "hhi"
+    #undef __INT_FAST8_MAX__
+    #define __INT_FAST8_MAX__ 127
+    #undef __INT_FAST8_TYPE__
+    #define __INT_FAST8_TYPE__ signed char
+    #undef __INT_FAST8_WIDTH__
+    #define __INT_FAST8_WIDTH__ 8
+    #undef __INT_LEAST16_FMTd__
+    #define __INT_LEAST16_FMTd__ "d"
+    #undef __INT_LEAST16_FMTi__
+    #define __INT_LEAST16_FMTi__ "i"
+    #undef __INT_LEAST16_MAX__
+    #define __INT_LEAST16_MAX__ 32767
+    #undef __INT_LEAST16_TYPE__
+    #define __INT_LEAST16_TYPE__ int
+    #undef __INT_LEAST16_WIDTH__
+    #define __INT_LEAST16_WIDTH__ 16
+    #undef __INT_LEAST32_FMTd__
+    #define __INT_LEAST32_FMTd__ "ld"
+    #undef __INT_LEAST32_FMTi__
+    #define __INT_LEAST32_FMTi__ "li"
+    #undef __INT_LEAST32_MAX__
+    #define __INT_LEAST32_MAX__ 2147483647L
+    #undef __INT_LEAST32_TYPE__
+    #define __INT_LEAST32_TYPE__ long int
+    #undef __INT_LEAST32_WIDTH__
+    #define __INT_LEAST32_WIDTH__ 32
+    #undef __INT_LEAST64_FMTd__
+    #define __INT_LEAST64_FMTd__ "lld"
+    #undef __INT_LEAST64_FMTi__
+    #define __INT_LEAST64_FMTi__ "lli"
+    #undef __INT_LEAST64_MAX__
+    #define __INT_LEAST64_MAX__ 9223372036854775807LL
+    #undef __INT_LEAST64_TYPE__
+    #define __INT_LEAST64_TYPE__ long long int
+    #undef __INT_LEAST64_WIDTH__
+    #define __INT_LEAST64_WIDTH__ 64
+    #undef __INT_LEAST8_FMTd__
+    #define __INT_LEAST8_FMTd__ "hhd"
+    #undef __INT_LEAST8_FMTi__
+    #define __INT_LEAST8_FMTi__ "hhi"
+    #undef __INT_LEAST8_MAX__
+    #define __INT_LEAST8_MAX__ 127
+    #undef __INT_LEAST8_TYPE__
+    #define __INT_LEAST8_TYPE__ signed char
+    #undef __INT_LEAST8_WIDTH__
+    #define __INT_LEAST8_WIDTH__ 8
+    #undef __INT_MAX__
+    #define __INT_MAX__ 32767
+    #undef __INT_WIDTH__
+    #define __INT_WIDTH__ 16
+    #undef __LDBL_DECIMAL_DIG__
+    #define __LDBL_DECIMAL_DIG__ 9
+    #undef __LDBL_DENORM_MIN__
+    #define __LDBL_DENORM_MIN__ 1.40129846e-45L
+    #undef __LDBL_DIG__
+    #define __LDBL_DIG__ 6
+    #undef __LDBL_EPSILON__
+    #define __LDBL_EPSILON__ 1.19209290e-7L
+    #undef __LDBL_HAS_DENORM__
+    #define __LDBL_HAS_DENORM__ 1
+    #undef __LDBL_HAS_INFINITY__
+    #define __LDBL_HAS_INFINITY__ 1
+    #undef __LDBL_HAS_QUIET_NAN__
+    #define __LDBL_HAS_QUIET_NAN__ 1
+    #undef __LDBL_MANT_DIG__
+    #define __LDBL_MANT_DIG__ 24
+    #undef __LDBL_MAX_10_EXP__
+    #define __LDBL_MAX_10_EXP__ 38
+    #undef __LDBL_MAX_EXP__
+    #define __LDBL_MAX_EXP__ 128
+    #undef __LDBL_MAX__
+    #define __LDBL_MAX__ 3.40282347e+38L
+    #undef __LDBL_MIN_10_EXP__
+    #define __LDBL_MIN_10_EXP__ (-37)
+    #undef __LDBL_MIN_EXP__
+    #define __LDBL_MIN_EXP__ (-125)
+    #undef __LDBL_MIN__
+    #define __LDBL_MIN__ 1.17549435e-38L
+    #undef __LITTLE_ENDIAN__
+    #define __LITTLE_ENDIAN__ 1
+    #undef __LLONG_WIDTH__
+    #define __LLONG_WIDTH__ 64
+    #undef __LONG_LONG_MAX__
+    #define __LONG_LONG_MAX__ 9223372036854775807LL
+    #undef __LONG_MAX__
+    #define __LONG_MAX__ 2147483647L
+    #undef __LONG_WIDTH__
+    #define __LONG_WIDTH__ 32
+    #undef __NO_INLINE__
+    #define __NO_INLINE__ 1
+    #undef __OBJC_BOOL_IS_BOOL
+    #define __OBJC_BOOL_IS_BOOL 0
+    #undef __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES
+    #define __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES 3
+    #undef __OPENCL_MEMORY_SCOPE_DEVICE
+    #define __OPENCL_MEMORY_SCOPE_DEVICE 2
+    #undef __OPENCL_MEMORY_SCOPE_SUB_GROUP
+    #define __OPENCL_MEMORY_SCOPE_SUB_GROUP 4
+    #undef __OPENCL_MEMORY_SCOPE_WORK_GROUP
+    #define __OPENCL_MEMORY_SCOPE_WORK_GROUP 1
+    #undef __OPENCL_MEMORY_SCOPE_WORK_ITEM
+    #define __OPENCL_MEMORY_SCOPE_WORK_ITEM 0
+    #undef __ORDER_BIG_ENDIAN__
+    #define __ORDER_BIG_ENDIAN__ 4321
+    #undef __ORDER_LITTLE_ENDIAN__
+    #define __ORDER_LITTLE_ENDIAN__ 1234
+    #undef __ORDER_PDP_ENDIAN__
+    #define __ORDER_PDP_ENDIAN__ 3412
+    #undef __POINTER_WIDTH__
+    #define __POINTER_WIDTH__ 16
+    #undef __PRAGMA_REDEFINE_EXTNAME
+    #define __PRAGMA_REDEFINE_EXTNAME 1
+    #undef __PTRDIFF_FMTd__
+    #define __PTRDIFF_FMTd__ "d"
+    #undef __PTRDIFF_FMTi__
+    #define __PTRDIFF_FMTi__ "i"
+    #undef __PTRDIFF_MAX__
+    #define __PTRDIFF_MAX__ 32767
+    #undef __PTRDIFF_TYPE__
+    #define __PTRDIFF_TYPE__ int
+    #undef __PTRDIFF_WIDTH__
+    #define __PTRDIFF_WIDTH__ 16
+    #undef __SCHAR_MAX__
+    #define __SCHAR_MAX__ 127
+    #undef __SHRT_MAX__
+    #define __SHRT_MAX__ 32767
+    #undef __SHRT_WIDTH__
+    #define __SHRT_WIDTH__ 16
+    #undef __SIG_ATOMIC_MAX__
+    #define __SIG_ATOMIC_MAX__ 127
+    #undef __SIG_ATOMIC_WIDTH__
+    #define __SIG_ATOMIC_WIDTH__ 8
+    #undef __SIZEOF_DOUBLE__
+    #define __SIZEOF_DOUBLE__ 4
+    #undef __SIZEOF_FLOAT__
+    #define __SIZEOF_FLOAT__ 4
+    #undef __SIZEOF_INT__
+    #define __SIZEOF_INT__ 2
+    #undef __SIZEOF_LONG_DOUBLE__
+    #define __SIZEOF_LONG_DOUBLE__ 4
+    #undef __SIZEOF_LONG_LONG__
+    #define __SIZEOF_LONG_LONG__ 8
+    #undef __SIZEOF_LONG__
+    #define __SIZEOF_LONG__ 4
+    #undef __SIZEOF_POINTER__
+    #define __SIZEOF_POINTER__ 2
+    #undef __SIZEOF_PTRDIFF_T__
+    #define __SIZEOF_PTRDIFF_T__ 2
+    #undef __SIZEOF_SHORT__
+    #define __SIZEOF_SHORT__ 2
+    #undef __SIZEOF_SIZE_T__
+    #define __SIZEOF_SIZE_T__ 2
+    #undef __SIZEOF_WCHAR_T__
+    #define __SIZEOF_WCHAR_T__ 2
+    #undef __SIZEOF_WINT_T__
+    #define __SIZEOF_WINT_T__ 2
+    #undef __SIZE_FMTX__
+    #define __SIZE_FMTX__ "X"
+    #undef __SIZE_FMTo__
+    #define __SIZE_FMTo__ "o"
+    #undef __SIZE_FMTu__
+    #define __SIZE_FMTu__ "u"
+    #undef __SIZE_FMTx__
+    #define __SIZE_FMTx__ "x"
+    #undef __SIZE_MAX__
+    #define __SIZE_MAX__ 65535U
+    #undef __SIZE_TYPE__
+    #define __SIZE_TYPE__ unsigned int
+    #undef __SIZE_WIDTH__
+    #define __SIZE_WIDTH__ 16
+    #undef __UINT16_C_SUFFIX__
+    #define __UINT16_C_SUFFIX__ U
+    #undef __UINT16_FMTX__
+    #define __UINT16_FMTX__ "X"
+    #undef __UINT16_FMTo__
+    #define __UINT16_FMTo__ "o"
+    #undef __UINT16_FMTu__
+    #define __UINT16_FMTu__ "u"
+    #undef __UINT16_FMTx__
+    #define __UINT16_FMTx__ "x"
+    #undef __UINT16_MAX__
+    #define __UINT16_MAX__ 65535U
+    #undef __UINT16_TYPE__
+    #define __UINT16_TYPE__ unsigned int
+    #undef __UINT32_C_SUFFIX__
+    #define __UINT32_C_SUFFIX__ UL
+    #undef __UINT32_FMTX__
+    #define __UINT32_FMTX__ "lX"
+    #undef __UINT32_FMTo__
+    #define __UINT32_FMTo__ "lo"
+    #undef __UINT32_FMTu__
+    #define __UINT32_FMTu__ "lu"
+    #undef __UINT32_FMTx__
+    #define __UINT32_FMTx__ "lx"
+    #undef __UINT32_MAX__
+    #define __UINT32_MAX__ 4294967295UL
+    #undef __UINT32_TYPE__
+    #define __UINT32_TYPE__ long unsigned int
+    #undef __UINT64_C_SUFFIX__
+    #define __UINT64_C_SUFFIX__ ULL
+    #undef __UINT64_FMTX__
+    #define __UINT64_FMTX__ "llX"
+    #undef __UINT64_FMTo__
+    #define __UINT64_FMTo__ "llo"
+    #undef __UINT64_FMTu__
+    #define __UINT64_FMTu__ "llu"
+    #undef __UINT64_FMTx__
+    #define __UINT64_FMTx__ "llx"
+    #undef __UINT64_MAX__
+    #define __UINT64_MAX__ 18446744073709551615ULL
+    #undef __UINT64_TYPE__
+    #define __UINT64_TYPE__ long long unsigned int
+    #undef __UINT8_C_SUFFIX__
+    #define __UINT8_C_SUFFIX__
+    #undef __UINT8_FMTX__
+    #define __UINT8_FMTX__ "hhX"
+    #undef __UINT8_FMTo__
+    #define __UINT8_FMTo__ "hho"
+    #undef __UINT8_FMTu__
+    #define __UINT8_FMTu__ "hhu"
+    #undef __UINT8_FMTx__
+    #define __UINT8_FMTx__ "hhx"
+    #undef __UINT8_MAX__
+    #define __UINT8_MAX__ 255
+    #undef __UINT8_TYPE__
+    #define __UINT8_TYPE__ unsigned char
+    #undef __UINTMAX_C_SUFFIX__
+    #define __UINTMAX_C_SUFFIX__ ULL
+    #undef __UINTMAX_FMTX__
+    #define __UINTMAX_FMTX__ "llX"
+    #undef __UINTMAX_FMTo__
+    #define __UINTMAX_FMTo__ "llo"
+    #undef __UINTMAX_FMTu__
+    #define __UINTMAX_FMTu__ "llu"
+    #undef __UINTMAX_FMTx__
+    #define __UINTMAX_FMTx__ "llx"
+    #undef __UINTMAX_MAX__
+    #define __UINTMAX_MAX__ 18446744073709551615ULL
+    #undef __UINTMAX_TYPE__
+    #define __UINTMAX_TYPE__ long long unsigned int
+    #undef __UINTMAX_WIDTH__
+    #define __UINTMAX_WIDTH__ 64
+    #undef __UINTPTR_FMTX__
+    #define __UINTPTR_FMTX__ "X"
+    #undef __UINTPTR_FMTo__
+    #define __UINTPTR_FMTo__ "o"
+    #undef __UINTPTR_FMTu__
+    #define __UINTPTR_FMTu__ "u"
+    #undef __UINTPTR_FMTx__
+    #define __UINTPTR_FMTx__ "x"
+    #undef __UINTPTR_MAX__
+    #define __UINTPTR_MAX__ 65535U
+    #undef __UINTPTR_TYPE__
+    #define __UINTPTR_TYPE__ unsigned int
+    #undef __UINTPTR_WIDTH__
+    #define __UINTPTR_WIDTH__ 16
+    #undef __UINT_FAST16_FMTX__
+    #define __UINT_FAST16_FMTX__ "X"
+    #undef __UINT_FAST16_FMTo__
+    #define __UINT_FAST16_FMTo__ "o"
+    #undef __UINT_FAST16_FMTu__
+    #define __UINT_FAST16_FMTu__ "u"
+    #undef __UINT_FAST16_FMTx__
+    #define __UINT_FAST16_FMTx__ "x"
+    #undef __UINT_FAST16_MAX__
+    #define __UINT_FAST16_MAX__ 65535U
+    #undef __UINT_FAST16_TYPE__
+    #define __UINT_FAST16_TYPE__ unsigned int
+    #undef __UINT_FAST32_FMTX__
+    #define __UINT_FAST32_FMTX__ "lX"
+    #undef __UINT_FAST32_FMTo__
+    #define __UINT_FAST32_FMTo__ "lo"
+    #undef __UINT_FAST32_FMTu__
+    #define __UINT_FAST32_FMTu__ "lu"
+    #undef __UINT_FAST32_FMTx__
+    #define __UINT_FAST32_FMTx__ "lx"
+    #undef __UINT_FAST32_MAX__
+    #define __UINT_FAST32_MAX__ 4294967295UL
+    #undef __UINT_FAST32_TYPE__
+    #define __UINT_FAST32_TYPE__ long unsigned int
+    #undef __UINT_FAST64_FMTX__
+    #define __UINT_FAST64_FMTX__ "llX"
+    #undef __UINT_FAST64_FMTo__
+    #define __UINT_FAST64_FMTo__ "llo"
+    #undef __UINT_FAST64_FMTu__
+    #define __UINT_FAST64_FMTu__ "llu"
+    #undef __UINT_FAST64_FMTx__
+    #define __UINT_FAST64_FMTx__ "llx"
+    #undef __UINT_FAST64_MAX__
+    #define __UINT_FAST64_MAX__ 18446744073709551615ULL
+    #undef __UINT_FAST64_TYPE__
+    #define __UINT_FAST64_TYPE__ long long unsigned int
+    #undef __UINT_FAST8_FMTX__
+    #define __UINT_FAST8_FMTX__ "hhX"
+    #undef __UINT_FAST8_FMTo__
+    #define __UINT_FAST8_FMTo__ "hho"
+    #undef __UINT_FAST8_FMTu__
+    #define __UINT_FAST8_FMTu__ "hhu"
+    #undef __UINT_FAST8_FMTx__
+    #define __UINT_FAST8_FMTx__ "hhx"
+    #undef __UINT_FAST8_MAX__
+    #define __UINT_FAST8_MAX__ 255
+    #undef __UINT_FAST8_TYPE__
+    #define __UINT_FAST8_TYPE__ unsigned char
+    #undef __UINT_LEAST16_FMTX__
+    #define __UINT_LEAST16_FMTX__ "X"
+    #undef __UINT_LEAST16_FMTo__
+    #define __UINT_LEAST16_FMTo__ "o"
+    #undef __UINT_LEAST16_FMTu__
+    #define __UINT_LEAST16_FMTu__ "u"
+    #undef __UINT_LEAST16_FMTx__
+    #define __UINT_LEAST16_FMTx__ "x"
+    #undef __UINT_LEAST16_MAX__
+    #define __UINT_LEAST16_MAX__ 65535U
+    #undef __UINT_LEAST16_TYPE__
+    #define __UINT_LEAST16_TYPE__ unsigned int
+    #undef __UINT_LEAST32_FMTX__
+    #define __UINT_LEAST32_FMTX__ "lX"
+    #undef __UINT_LEAST32_FMTo__
+    #define __UINT_LEAST32_FMTo__ "lo"
+    #undef __UINT_LEAST32_FMTu__
+    #define __UINT_LEAST32_FMTu__ "lu"
+    #undef __UINT_LEAST32_FMTx__
+    #define __UINT_LEAST32_FMTx__ "lx"
+    #undef __UINT_LEAST32_MAX__
+    #define __UINT_LEAST32_MAX__ 4294967295UL
+    #undef __UINT_LEAST32_TYPE__
+    #define __UINT_LEAST32_TYPE__ long unsigned int
+    #undef __UINT_LEAST64_FMTX__
+    #define __UINT_LEAST64_FMTX__ "llX"
+    #undef __UINT_LEAST64_FMTo__
+    #define __UINT_LEAST64_FMTo__ "llo"
+    #undef __UINT_LEAST64_FMTu__
+    #define __UINT_LEAST64_FMTu__ "llu"
+    #undef __UINT_LEAST64_FMTx__
+    #define __UINT_LEAST64_FMTx__ "llx"
+    #undef __UINT_LEAST64_MAX__
+    #define __UINT_LEAST64_MAX__ 18446744073709551615ULL
+    #undef __UINT_LEAST64_TYPE__
+    #define __UINT_LEAST64_TYPE__ long long unsigned int
+    #undef __UINT_LEAST8_FMTX__
+    #define __UINT_LEAST8_FMTX__ "hhX"
+    #undef __UINT_LEAST8_FMTo__
+    #define __UINT_LEAST8_FMTo__ "hho"
+    #undef __UINT_LEAST8_FMTu__
+    #define __UINT_LEAST8_FMTu__ "hhu"
+    #undef __UINT_LEAST8_FMTx__
+    #define __UINT_LEAST8_FMTx__ "hhx"
+    #undef __UINT_LEAST8_MAX__
+    #define __UINT_LEAST8_MAX__ 255
+    #undef __UINT_LEAST8_TYPE__
+    #define __UINT_LEAST8_TYPE__ unsigned char
+    #undef __USER_LABEL_PREFIX__
+    #define __USER_LABEL_PREFIX__
+    #undef __VERSION__
+    #define __VERSION__ "Clang 15.0.7"
+    #undef __WCHAR_MAX__
+    #define __WCHAR_MAX__ 32767
+    #undef __WCHAR_TYPE__
+    #define __WCHAR_TYPE__ int
+    #undef __WCHAR_WIDTH__
+    #define __WCHAR_WIDTH__ 16
+    #undef __WINT_MAX__
+    #define __WINT_MAX__ 32767
+    #undef __WINT_TYPE__
+    #define __WINT_TYPE__ int
+    #undef __WINT_WIDTH__
+    #define __WINT_WIDTH__ 16
+    #undef __clang__
+    #define __clang__ 1
+    #undef __clang_literal_encoding__
+    #define __clang_literal_encoding__ "UTF-8"
+    #undef __clang_major__
+    #define __clang_major__ 15
+    #undef __clang_minor__
+    #define __clang_minor__ 0
+    #undef __clang_patchlevel__
+    #define __clang_patchlevel__ 7
+    #undef __clang_version__
+    #define __clang_version__ "15.0.7 "
+    #undef __clang_wide_literal_encoding__
+    #define __clang_wide_literal_encoding__ "UTF-16"
+    #undef __llvm__
+    #define __llvm__ 1
+eof: (-1)
+errno:
+    e2big: ((int)(66072050 & 0xffff))
+    eacces: ((int)(66072050 & 0xffff))
+    eaddrinuse: ((int)(66072050 & 0xffff))
+    eaddrnotavail: ((int)(66072050 & 0xffff))
+    eafnosupport: ((int)(66072050 & 0xffff))
+    eagain: ((int)(66072050 & 0xffff))
+    ealready: ((int)(66072050 & 0xffff))
+    ebadf: ((int)(66072050 & 0xffff))
+    ebusy: ((int)(66072050 & 0xffff))
+    echild: ((int)(66072050 & 0xffff))
+    econnaborted: ((int)(66072050 & 0xffff))
+    econnrefused: ((int)(66072050 & 0xffff))
+    econnreset: ((int)(66072050 & 0xffff))
+    edeadlk: ((int)(66072050 & 0xffff))
+    edestaddrreq: ((int)(66072050 & 0xffff))
+    edom: '33'
+    eexist: ((int)(66072050 & 0xffff))
+    efault: ((int)(66072050 & 0xffff))
+    efbig: ((int)(66072050 & 0xffff))
+    ehostunreach: ((int)(66072050 & 0xffff))
+    eilseq: ((int)(66072050 & 0xffff))
+    einprogress: ((int)(66072050 & 0xffff))
+    eintr: ((int)(2453066 & 0x7fff))
+    einval: ((int)(66072050 & 0xffff))
+    eio: ((int)(66072050 & 0xffff))
+    eisconn: ((int)(66072050 & 0xffff))
+    eisdir: ((int)(66072050 & 0xffff))
+    eloop: ((int)(66072050 & 0xffff))
+    emfile: ((int)(66072050 & 0xffff))
+    emlink: ((int)(66072050 & 0xffff))
+    emsgsize: ((int)(66072050 & 0xffff))
+    enametoolong: ((int)(66072050 & 0xffff))
+    enetdown: ((int)(66072050 & 0xffff))
+    enetreset: ((int)(66072050 & 0xffff))
+    enetunreach: ((int)(66072050 & 0xffff))
+    enfile: ((int)(66072050 & 0xffff))
+    enobufs: ((int)(66072050 & 0xffff))
+    enodev: ((int)(66072050 & 0xffff))
+    enoent: ((int)(66072050 & 0xffff))
+    enoexec: ((int)(66072050 & 0xffff))
+    enolck: ((int)(66072050 & 0xffff))
+    enomem: ((int)(66072050 & 0xffff))
+    enomsg: ((int)(66072050 & 0xffff))
+    enoprotoopt: ((int)(66072050 & 0xffff))
+    enospc: ((int)(66072050 & 0xffff))
+    enosys: ((int)(66081697 & 0x7fff))
+    enotconn: ((int)(66072050 & 0xffff))
+    enotdir: ((int)(66072050 & 0xffff))
+    enotempty: ((int)(66072050 & 0xffff))
+    enotsock: ((int)(66072050 & 0xffff))
+    enotty: ((int)(66072050 & 0xffff))
+    enxio: ((int)(66072050 & 0xffff))
+    eopnotsupp: ((int)(66072050 & 0xffff))
+    eperm: ((int)(66072050 & 0xffff))
+    epipe: ((int)(66072050 & 0xffff))
+    eprotonosupport: ((int)(66072050 & 0xffff))
+    eprototype: ((int)(66072050 & 0xffff))
+    erange: '34'
+    erofs: ((int)(66072050 & 0xffff))
+    espipe: ((int)(66072050 & 0xffff))
+    esrch: ((int)(66072050 & 0xffff))
+    etimedout: ((int)(66072050 & 0xffff))
+    ewouldblock: ((int)(66072050 & 0xffff))
+    exdev: ((int)(66072050 & 0xffff))
+filename_max: ''
+fopen_max: ''
+has__builtin_va_list: true
+host_name_max: '64'
+int_fast16_t: int
+int_fast32_t: long
+int_fast64_t: long long
+int_fast8_t: signed char
+intptr_t: int
+l_tmpnam: ''
+little_endian: true
+machdep_name: machdep_avr_8
+mb_cur_max: ((size_t)16)
+nsig: ''
+path_max: '4096'
+posix_version: ''
+ptrdiff_t: int
+rand_max: '0x7FFF'
+sig_atomic_t: ''
+size_t: unsigned int
+sizeof_double: 4
+sizeof_float: 4
+sizeof_fun: 1
+sizeof_int: 2
+sizeof_long: 4
+sizeof_longdouble: 4
+sizeof_longlong: 8
+sizeof_ptr: 2
+sizeof_short: 2
+sizeof_void: 1
+ssize_t: ''
+time_t: unsigned long
+tmp_max: ''
+tty_name_max: '32'
+uint_fast16_t: unsigned int
+uint_fast32_t: unsigned long
+uint_fast64_t: unsigned long long
+uint_fast8_t: unsigned char
+uintptr_t: unsigned int
+version: clang version 15.0.7
+wchar_t: int
+weof: (0xffffffffu)
+wint_t: int
+wordsize: '32'
diff --git a/share/machdeps/machdep_gcc_x86_16.yaml b/share/machdeps/machdep_gcc_x86_16.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..87f4e68c223a9cdc2860fbc0b398b3c69d428327
--- /dev/null
+++ b/share/machdeps/machdep_gcc_x86_16.yaml
@@ -0,0 +1,928 @@
+alignof_aligned: 8
+alignof_double: 8
+alignof_float: 2
+alignof_fun: 1
+alignof_int: 2
+alignof_long: 4
+alignof_longdouble: 16
+alignof_longlong: 4
+alignof_ptr: 4
+alignof_short: 2
+alignof_str: 1
+char_is_unsigned: false
+compiler: gcc
+cpp_arch_flags:
+- -m16
+
+# adapted from the builtin macros of gcc_x86_32
+custom_defs: |
+    #undef __SSP_STRONG__
+    #define __SSP_STRONG__ 3
+    #undef __DBL_MIN_EXP__
+    #define __DBL_MIN_EXP__ (-1021)
+    #undef __UINT_LEAST16_MAX__
+    #define __UINT_LEAST16_MAX__ 0xffff
+    #undef __FLT16_HAS_QUIET_NAN__
+    #define __FLT16_HAS_QUIET_NAN__ 1
+    #undef __ATOMIC_ACQUIRE
+    #define __ATOMIC_ACQUIRE 2
+    #undef __FLT128_MAX_10_EXP__
+    #define __FLT128_MAX_10_EXP__ 4932
+    #undef __FLT_MIN__
+    #define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F
+    #undef __GCC_IEC_559_COMPLEX
+    #define __GCC_IEC_559_COMPLEX 2
+    #undef __UINT_LEAST8_TYPE__
+    #define __UINT_LEAST8_TYPE__ unsigned char
+    #undef __SIZEOF_FLOAT80__
+    #define __SIZEOF_FLOAT80__ 12
+    #undef __INTMAX_C
+    #define __INTMAX_C(c) c ## LL
+    #undef __CHAR_BIT__
+    #define __CHAR_BIT__ 8
+    #undef __UINT8_MAX__
+    #define __UINT8_MAX__ 0xff
+    #undef __SCHAR_WIDTH__
+    #define __SCHAR_WIDTH__ 8
+    #undef __WINT_MAX__
+    #define __WINT_MAX__ 0xffffffffU
+    #undef __FLT32_MIN_EXP__
+    #define __FLT32_MIN_EXP__ (-125)
+    #undef __ORDER_LITTLE_ENDIAN__
+    #define __ORDER_LITTLE_ENDIAN__ 1234
+    #undef __SIZE_MAX__
+    #define __SIZE_MAX__ 0xffffffffU
+    #undef __WCHAR_MAX__
+    #define __WCHAR_MAX__ 0x7fffffffL
+    #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
+    #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
+    #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
+    #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
+    #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
+    #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
+    #undef __GCC_ATOMIC_CHAR_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR_LOCK_FREE 2
+    #undef __GCC_IEC_559
+    #define __GCC_IEC_559 2
+    #undef __FLT32X_DECIMAL_DIG__
+    #define __FLT32X_DECIMAL_DIG__ 17
+    #undef __FLT_EVAL_METHOD__
+    #define __FLT_EVAL_METHOD__ 2
+    #undef __FLT64_DECIMAL_DIG__
+    #define __FLT64_DECIMAL_DIG__ 17
+    #undef __GCC_ATOMIC_CHAR32_T_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
+    #undef __UINT_FAST64_MAX__
+    #define __UINT_FAST64_MAX__ 0xffffffffffffffffULL
+    #undef __SIG_ATOMIC_TYPE__
+    #define __SIG_ATOMIC_TYPE__ int
+    #undef __DBL_MIN_10_EXP__
+    #define __DBL_MIN_10_EXP__ (-307)
+    #undef __FINITE_MATH_ONLY__
+    #define __FINITE_MATH_ONLY__ 0
+    #undef __FLT32X_MAX_EXP__
+    #define __FLT32X_MAX_EXP__ 1024
+    #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
+    #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+    #undef __FLT32_HAS_DENORM__
+    #define __FLT32_HAS_DENORM__ 1
+    #undef __UINT_FAST8_MAX__
+    #define __UINT_FAST8_MAX__ 0xff
+    #undef __FLT32_MAX_10_EXP__
+    #define __FLT32_MAX_10_EXP__ 38
+    #undef __DEC64_MAX_EXP__
+    #define __DEC64_MAX_EXP__ 385
+    #undef __INT8_C
+    #define __INT8_C(c) c
+    #undef __INT_LEAST8_WIDTH__
+    #define __INT_LEAST8_WIDTH__ 8
+    #undef __UINT_LEAST64_MAX__
+    #define __UINT_LEAST64_MAX__ 0xffffffffffffffffULL
+    #undef __SHRT_MAX__
+    #define __SHRT_MAX__ 0x7fff
+    #undef __LDBL_MAX__
+    #define __LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L
+    #undef __FLT64X_MAX_10_EXP__
+    #define __FLT64X_MAX_10_EXP__ 4932
+    #undef __LDBL_IS_IEC_60559__
+    #define __LDBL_IS_IEC_60559__ 2
+    #undef __FLT64X_HAS_QUIET_NAN__
+    #define __FLT64X_HAS_QUIET_NAN__ 1
+    #undef __UINT_LEAST8_MAX__
+    #define __UINT_LEAST8_MAX__ 0xff
+    #undef __GCC_ATOMIC_BOOL_LOCK_FREE
+    #define __GCC_ATOMIC_BOOL_LOCK_FREE 2
+    #undef __LAHF_SAHF__
+    #define __LAHF_SAHF__ 1
+    #undef __FLT128_DENORM_MIN__
+    #define __FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128
+    #undef __UINTMAX_TYPE__
+    #define __UINTMAX_TYPE__ long long unsigned int
+    #undef __linux
+    #define __linux 1
+    #undef __DEC32_EPSILON__
+    #define __DEC32_EPSILON__ 1E-6DF
+    #undef __FLT_EVAL_METHOD_TS_18661_3__
+    #define __FLT_EVAL_METHOD_TS_18661_3__ 2
+    #undef __unix
+    #define __unix 1
+    #undef __UINT32_MAX__
+    #define __UINT32_MAX__ 0xffffffffU
+    #undef __DBL_DENORM_MIN__
+    #define __DBL_DENORM_MIN__ ((double)4.94065645841246544176568792868221372e-324L)
+    #undef __FLT128_MIN_EXP__
+    #define __FLT128_MIN_EXP__ (-16381)
+    #undef __WINT_MIN__
+    #define __WINT_MIN__ 0U
+    #undef __FLT128_MIN_10_EXP__
+    #define __FLT128_MIN_10_EXP__ (-4931)
+    #undef __FLT32X_IS_IEC_60559__
+    #define __FLT32X_IS_IEC_60559__ 2
+    #undef __INT_LEAST16_WIDTH__
+    #define __INT_LEAST16_WIDTH__ 16
+    #undef __SCHAR_MAX__
+    #define __SCHAR_MAX__ 0x7f
+    #undef __FLT128_MANT_DIG__
+    #define __FLT128_MANT_DIG__ 113
+    #undef __WCHAR_MIN__
+    #define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
+    #undef __INT64_C
+    #define __INT64_C(c) c ## LL
+    #undef __GCC_ATOMIC_POINTER_LOCK_FREE
+    #define __GCC_ATOMIC_POINTER_LOCK_FREE 2
+    #undef __FLT32X_MANT_DIG__
+    #define __FLT32X_MANT_DIG__ 53
+    #undef __FLT64X_EPSILON__
+    #define __FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x
+    #undef __DEC64_MIN_EXP__
+    #define __DEC64_MIN_EXP__ (-382)
+    #undef __DBL_DIG__
+    #define __DBL_DIG__ 15
+    #undef __FLT32_DIG__
+    #define __FLT32_DIG__ 6
+    #undef __FLT_EPSILON__
+    #define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F
+    #undef __SHRT_WIDTH__
+    #define __SHRT_WIDTH__ 16
+    #undef __FLT32_IS_IEC_60559__
+    #define __FLT32_IS_IEC_60559__ 2
+    #undef __LDBL_MIN__
+    #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
+    #undef __DBL_IS_IEC_60559__
+    #define __DBL_IS_IEC_60559__ 2
+    #undef __DEC32_MAX__
+    #define __DEC32_MAX__ 9.999999E96DF
+    #undef __FLT64X_DENORM_MIN__
+    #define __FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x
+    #undef __FLT32X_HAS_INFINITY__
+    #define __FLT32X_HAS_INFINITY__ 1
+    #undef __INT32_MAX__
+    #define __INT32_MAX__ 0x7fffffff
+    #undef __FLT16_DIG__
+    #define __FLT16_DIG__ 3
+    #undef __unix__
+    #define __unix__ 1
+    #undef __INT_WIDTH__
+    #define __INT_WIDTH__ 16
+    #undef __SIZEOF_LONG__
+    #define __SIZEOF_LONG__ 4
+    #undef __UINT16_C
+    #define __UINT16_C(c) c
+    #undef __DECIMAL_DIG__
+    #define __DECIMAL_DIG__ 21
+    #undef __FLT64_EPSILON__
+    #define __FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64
+    #undef __gnu_linux__
+    #define __gnu_linux__ 1
+    #undef __FLT128_IS_IEC_60559__
+    #define __FLT128_IS_IEC_60559__ 2
+    #undef __FLT64X_MIN_10_EXP__
+    #define __FLT64X_MIN_10_EXP__ (-4931)
+    #undef __LDBL_HAS_QUIET_NAN__
+    #define __LDBL_HAS_QUIET_NAN__ 1
+    #undef __FLT16_MIN_EXP__
+    #define __FLT16_MIN_EXP__ (-13)
+    #undef __FLT64_MANT_DIG__
+    #define __FLT64_MANT_DIG__ 53
+    #undef __FLT64X_MANT_DIG__
+    #define __FLT64X_MANT_DIG__ 64
+    #undef __GNUC__
+    #define __GNUC__ 12
+    #undef __pie__
+    #define __pie__ 2
+    #undef __MMX__
+    #define __MMX__ 1
+    #undef __FLT_HAS_DENORM__
+    #define __FLT_HAS_DENORM__ 1
+    #undef __SIZEOF_LONG_DOUBLE__
+    #define __SIZEOF_LONG_DOUBLE__ 12
+    #undef __BIGGEST_ALIGNMENT__
+    #define __BIGGEST_ALIGNMENT__ 16
+    #undef __FLT64_MAX_10_EXP__
+    #define __FLT64_MAX_10_EXP__ 308
+    #undef __FLT16_MAX_10_EXP__
+    #define __FLT16_MAX_10_EXP__ 4
+    #undef __DBL_MAX__
+    #define __DBL_MAX__ ((double)1.79769313486231570814527423731704357e+308L)
+    #undef __INT_FAST32_MAX__
+    #define __INT_FAST32_MAX__ 0x7fffffff
+    #undef __DBL_HAS_INFINITY__
+    #define __DBL_HAS_INFINITY__ 1
+    #undef __SIZEOF_FLOAT__
+    #define __SIZEOF_FLOAT__ 4
+    #undef __HAVE_SPECULATION_SAFE_VALUE
+    #define __HAVE_SPECULATION_SAFE_VALUE 1
+    #undef __DEC32_MIN_EXP__
+    #define __DEC32_MIN_EXP__ (-94)
+    #undef __INTPTR_WIDTH__
+    #define __INTPTR_WIDTH__ 32
+    #undef __FLT64X_HAS_INFINITY__
+    #define __FLT64X_HAS_INFINITY__ 1
+    #undef __UINT_LEAST32_MAX__
+    #define __UINT_LEAST32_MAX__ 0xffffffffU
+    #undef __FLT32X_HAS_DENORM__
+    #define __FLT32X_HAS_DENORM__ 1
+    #undef __INT_FAST16_TYPE__
+    #define __INT_FAST16_TYPE__ int
+    #undef __LDBL_HAS_DENORM__
+    #define __LDBL_HAS_DENORM__ 1
+    #undef __SEG_GS
+    #define __SEG_GS 1
+    #undef __FLT128_HAS_INFINITY__
+    #define __FLT128_HAS_INFINITY__ 1
+    #undef __DEC32_MIN__
+    #define __DEC32_MIN__ 1E-95DF
+    #undef __DBL_MAX_EXP__
+    #define __DBL_MAX_EXP__ 1024
+    #undef __WCHAR_WIDTH__
+    #define __WCHAR_WIDTH__ 16
+    #undef __FLT32_MAX__
+    #define __FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32
+    #undef __DEC128_EPSILON__
+    #define __DEC128_EPSILON__ 1E-33DL
+    #undef __FLT16_DECIMAL_DIG__
+    #define __FLT16_DECIMAL_DIG__ 5
+    #undef __ATOMIC_HLE_RELEASE
+    #define __ATOMIC_HLE_RELEASE 131072
+    #undef __PTRDIFF_MAX__
+    #define __PTRDIFF_MAX__ 0x7fffffff
+    #undef __ATOMIC_HLE_ACQUIRE
+    #define __ATOMIC_HLE_ACQUIRE 65536
+    #undef __LONG_LONG_MAX__
+    #define __LONG_LONG_MAX__ 0x7fffffffffffffffLL
+    #undef __SIZEOF_SIZE_T__
+    #define __SIZEOF_SIZE_T__ 2
+    #undef __FLT64X_MIN_EXP__
+    #define __FLT64X_MIN_EXP__ (-16381)
+    #undef __SIZEOF_WINT_T__
+    #define __SIZEOF_WINT_T__ 4
+    #undef __LONG_LONG_WIDTH__
+    #define __LONG_LONG_WIDTH__ 64
+    #undef __FLT32_MAX_EXP__
+    #define __FLT32_MAX_EXP__ 128
+    #undef __GXX_ABI_VERSION
+    #define __GXX_ABI_VERSION 1017
+    #undef __FLT_MIN_EXP__
+    #define __FLT_MIN_EXP__ (-125)
+    #undef __GCC_HAVE_DWARF2_CFI_ASM
+    #define __GCC_HAVE_DWARF2_CFI_ASM 1
+    #undef __INT16_MAX__
+    #define __INT16_MAX__ 0x7fff
+    #undef __INT_FAST64_TYPE__
+    #define __INT_FAST64_TYPE__ long long int
+    #undef __FLT64_DENORM_MIN__
+    #define __FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64
+    #undef __DBL_MIN__
+    #define __DBL_MIN__ ((double)2.22507385850720138309023271733240406e-308L)
+    #undef __FLT16_DENORM_MIN__
+    #define __FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16
+    #undef __FLT128_EPSILON__
+    #define __FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128
+    #undef __FLT64X_NORM_MAX__
+    #define __FLT64X_NORM_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+    #undef __SIZEOF_POINTER__
+    #define __SIZEOF_POINTER__ 4
+    #undef __DBL_HAS_QUIET_NAN__
+    #define __DBL_HAS_QUIET_NAN__ 1
+    #undef __FLT32X_EPSILON__
+    #define __FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x
+    #undef __DECIMAL_BID_FORMAT__
+    #define __DECIMAL_BID_FORMAT__ 1
+    #undef __FLT64_MIN_EXP__
+    #define __FLT64_MIN_EXP__ (-1021)
+    #undef __FLT64_MIN_10_EXP__
+    #define __FLT64_MIN_10_EXP__ (-307)
+    #undef __FLT16_MIN_10_EXP__
+    #define __FLT16_MIN_10_EXP__ (-4)
+    #undef __FLT64X_DECIMAL_DIG__
+    #define __FLT64X_DECIMAL_DIG__ 21
+    #undef __DEC128_MIN__
+    #define __DEC128_MIN__ 1E-6143DL
+    #undef __REGISTER_PREFIX__
+    #define __REGISTER_PREFIX__
+    #undef __UINT16_MAX__
+    #define __UINT16_MAX__ 0xffff
+    #undef __DBL_HAS_DENORM__
+    #define __DBL_HAS_DENORM__ 1
+    #undef __LDBL_HAS_INFINITY__
+    #define __LDBL_HAS_INFINITY__ 1
+    #undef __FLT32_MIN__
+    #define __FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32
+    #undef __UINT8_TYPE__
+    #define __UINT8_TYPE__ unsigned char
+    #undef __FLT_DIG__
+    #define __FLT_DIG__ 6
+    #undef __NO_INLINE__
+    #define __NO_INLINE__ 1
+    #undef __DEC_EVAL_METHOD__
+    #define __DEC_EVAL_METHOD__ 2
+    #undef __DEC128_MAX__
+    #define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
+    #undef __i386
+    #define __i386 1
+    #undef __FLT_MANT_DIG__
+    #define __FLT_MANT_DIG__ 24
+    #undef __LDBL_DECIMAL_DIG__
+    #define __LDBL_DECIMAL_DIG__ 21
+    #undef __VERSION__
+    #define __VERSION__ "12.2.1 20230201"
+    #undef __UINT64_C
+    #define __UINT64_C(c) c ## ULL
+    #undef _STDC_PREDEF_H
+    #define _STDC_PREDEF_H 1
+    #undef __INT_LEAST32_MAX__
+    #define __INT_LEAST32_MAX__ 0x7fffffff
+    #undef __GCC_ATOMIC_INT_LOCK_FREE
+    #define __GCC_ATOMIC_INT_LOCK_FREE 2
+    #undef __FLT128_MAX_EXP__
+    #define __FLT128_MAX_EXP__ 16384
+    #undef __FLT32_MANT_DIG__
+    #define __FLT32_MANT_DIG__ 24
+    #undef __FLOAT_WORD_ORDER__
+    #define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
+    #undef __FLT32X_MIN_EXP__
+    #define __FLT32X_MIN_EXP__ (-1021)
+    #undef i386
+    #define i386 1
+    #undef __FLT128_HAS_DENORM__
+    #define __FLT128_HAS_DENORM__ 1
+    #undef __FLT32_DECIMAL_DIG__
+    #define __FLT32_DECIMAL_DIG__ 9
+    #undef __FLT128_DIG__
+    #define __FLT128_DIG__ 33
+    #undef __INT32_C
+    #define __INT32_C(c) c ## L
+    #undef __DEC64_EPSILON__
+    #define __DEC64_EPSILON__ 1E-15DD
+    #undef __ORDER_PDP_ENDIAN__
+    #define __ORDER_PDP_ENDIAN__ 3412
+    #undef __DEC128_MIN_EXP__
+    #define __DEC128_MIN_EXP__ (-6142)
+    #undef __code_model_32__
+    #define __code_model_32__ 1
+    #undef __INT_FAST32_TYPE__
+    #define __INT_FAST32_TYPE__ long
+    #undef __UINT_LEAST16_TYPE__
+    #define __UINT_LEAST16_TYPE__ short unsigned int
+    #undef unix
+    #define unix 1
+    #undef __i386__
+    #define __i386__ 1
+    #undef __SIZE_TYPE__
+    #define __SIZE_TYPE__ unsigned int
+    #undef __UINT64_MAX__
+    #define __UINT64_MAX__ 0xffffffffffffffffULL
+    #undef __FLT_IS_IEC_60559__
+    #define __FLT_IS_IEC_60559__ 2
+    #undef __GNUC_WIDE_EXECUTION_CHARSET_NAME
+    #define __GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE"
+    #undef __FLT64X_DIG__
+    #define __FLT64X_DIG__ 18
+    #undef __INT8_TYPE__
+    #define __INT8_TYPE__ signed char
+    #undef __ELF__
+    #define __ELF__ 1
+    #undef __GCC_ASM_FLAG_OUTPUTS__
+    #define __GCC_ASM_FLAG_OUTPUTS__ 1
+    #undef __UINT32_TYPE__
+    #define __UINT32_TYPE__ unsigned long
+    #undef __FLT_RADIX__
+    #define __FLT_RADIX__ 2
+    #undef __INT_LEAST16_TYPE__
+    #define __INT_LEAST16_TYPE__ short int
+    #undef __LDBL_EPSILON__
+    #define __LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L
+    #undef __UINTMAX_C
+    #define __UINTMAX_C(c) c ## ULL
+    #undef __k8
+    #define __k8 1
+    #undef __FLT32X_MIN__
+    #define __FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x
+    #undef __SIG_ATOMIC_MAX__
+    #define __SIG_ATOMIC_MAX__ 0x7fffffff
+    #undef __GCC_ATOMIC_WCHAR_T_LOCK_FREE
+    #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
+    #undef __USER_LABEL_PREFIX__
+    #define __USER_LABEL_PREFIX__
+    #undef __SIZEOF_PTRDIFF_T__
+    #define __SIZEOF_PTRDIFF_T__ 4
+    #undef __LDBL_DIG__
+    #define __LDBL_DIG__ 18
+    #undef __FLT64_IS_IEC_60559__
+    #define __FLT64_IS_IEC_60559__ 2
+    #undef __FLT16_IS_IEC_60559__
+    #define __FLT16_IS_IEC_60559__ 2
+    #undef __FLT16_MAX_EXP__
+    #define __FLT16_MAX_EXP__ 16
+    #undef __DEC32_SUBNORMAL_MIN__
+    #define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
+    #undef __INT_FAST16_MAX__
+    #define __INT_FAST16_MAX__ 0x7fffffff
+    #undef __GCC_CONSTRUCTIVE_SIZE
+    #define __GCC_CONSTRUCTIVE_SIZE 64
+    #undef __FLT64_DIG__
+    #define __FLT64_DIG__ 15
+    #undef __UINT_FAST32_MAX__
+    #define __UINT_FAST32_MAX__ 0xffffffffU
+    #undef __UINT_LEAST64_TYPE__
+    #define __UINT_LEAST64_TYPE__ long long unsigned int
+    #undef __FLT16_EPSILON__
+    #define __FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16
+    #undef __ILP32__
+    #define __ILP32__ 1
+    #undef __FLT_HAS_QUIET_NAN__
+    #define __FLT_HAS_QUIET_NAN__ 1
+    #undef __FLT_MAX_10_EXP__
+    #define __FLT_MAX_10_EXP__ 38
+    #undef __LONG_MAX__
+    #define __LONG_MAX__ 0x7fffffffL
+    #undef __FLT64X_HAS_DENORM__
+    #define __FLT64X_HAS_DENORM__ 1
+    #undef __DEC128_SUBNORMAL_MIN__
+    #define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
+    #undef __FLT_HAS_INFINITY__
+    #define __FLT_HAS_INFINITY__ 1
+    #undef __GNUC_EXECUTION_CHARSET_NAME
+    #define __GNUC_EXECUTION_CHARSET_NAME "UTF-8"
+    #undef _ILP32
+    #define _ILP32 1
+    #undef __UINT_FAST16_TYPE__
+    #define __UINT_FAST16_TYPE__ unsigned int
+    #undef __DEC64_MAX__
+    #define __DEC64_MAX__ 9.999999999999999E384DD
+    #undef __INT_FAST32_WIDTH__
+    #define __INT_FAST32_WIDTH__ 32
+    #undef __CHAR16_TYPE__
+    #define __CHAR16_TYPE__ short unsigned int
+    #undef __PRAGMA_REDEFINE_EXTNAME
+    #define __PRAGMA_REDEFINE_EXTNAME 1
+    #undef __SIZE_WIDTH__
+    #define __SIZE_WIDTH__ 32
+    #undef __SEG_FS
+    #define __SEG_FS 1
+    #undef __INT_LEAST16_MAX__
+    #define __INT_LEAST16_MAX__ 0x7fff
+    #undef __FLT16_NORM_MAX__
+    #define __FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16
+    #undef __DEC64_MANT_DIG__
+    #define __DEC64_MANT_DIG__ 16
+    #undef __INT64_MAX__
+    #define __INT64_MAX__ 0x7fffffffffffffffLL
+    #undef __FLT32_DENORM_MIN__
+    #define __FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32
+    #undef __SIG_ATOMIC_WIDTH__
+    #define __SIG_ATOMIC_WIDTH__ 32
+    #undef __INT_LEAST64_TYPE__
+    #define __INT_LEAST64_TYPE__ long long int
+    #undef __INT16_TYPE__
+    #define __INT16_TYPE__ short int
+    #undef __INT_LEAST8_TYPE__
+    #define __INT_LEAST8_TYPE__ signed char
+    #undef __FLT16_MAX__
+    #define __FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16
+    #undef __SIZEOF_INT__
+    #define __SIZEOF_INT__ 4
+    #undef __DEC32_MAX_EXP__
+    #define __DEC32_MAX_EXP__ 97
+    #undef __INT_FAST8_MAX__
+    #define __INT_FAST8_MAX__ 0x7f
+    #undef __FLT128_MAX__
+    #define __FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128
+    #undef __INTPTR_MAX__
+    #define __INTPTR_MAX__ 0x7fffffff
+    #undef linux
+    #define linux 1
+    #undef __FLT64_HAS_QUIET_NAN__
+    #define __FLT64_HAS_QUIET_NAN__ 1
+    #undef __FLT32_MIN_10_EXP__
+    #define __FLT32_MIN_10_EXP__ (-37)
+    #undef __FLT32X_DIG__
+    #define __FLT32X_DIG__ 15
+    #undef __PTRDIFF_WIDTH__
+    #define __PTRDIFF_WIDTH__ 16
+    #undef __LDBL_MANT_DIG__
+    #define __LDBL_MANT_DIG__ 64
+    #undef __FLT64_HAS_INFINITY__
+    #define __FLT64_HAS_INFINITY__ 1
+    #undef __FLT64X_MAX__
+    #define __FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+    #undef __FLT16_HAS_INFINITY__
+    #define __FLT16_HAS_INFINITY__ 1
+    #undef __SIG_ATOMIC_MIN__
+    #define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
+    #undef __GCC_ATOMIC_LONG_LOCK_FREE
+    #define __GCC_ATOMIC_LONG_LOCK_FREE 2
+    #undef __DEC32_MANT_DIG__
+    #define __DEC32_MANT_DIG__ 7
+    #undef __FLT16_MANT_DIG__
+    #define __FLT16_MANT_DIG__ 11
+    #undef __k8__
+    #define __k8__ 1
+    #undef __INTPTR_TYPE__
+    #define __INTPTR_TYPE__ long
+    #undef __UINT16_TYPE__
+    #define __UINT16_TYPE__ short unsigned int
+    #undef __WCHAR_TYPE__
+    #define __WCHAR_TYPE__ int
+    #undef __pic__
+    #define __pic__ 2
+    #undef __UINTPTR_MAX__
+    #define __UINTPTR_MAX__ 0xffffffffU
+    #undef __INT_FAST64_WIDTH__
+    #define __INT_FAST64_WIDTH__ 64
+    #undef __INT_FAST64_MAX__
+    #define __INT_FAST64_MAX__ 0x7fffffffffffffffLL
+    #undef __GCC_ATOMIC_TEST_AND_SET_TRUEVAL
+    #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
+    #undef __FLT_NORM_MAX__
+    #define __FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F
+    #undef __FLT32_HAS_INFINITY__
+    #define __FLT32_HAS_INFINITY__ 1
+    #undef __FLT64X_MAX_EXP__
+    #define __FLT64X_MAX_EXP__ 16384
+    #undef __UINT_FAST64_TYPE__
+    #define __UINT_FAST64_TYPE__ long long unsigned int
+    #undef __INT_MAX__
+    #define __INT_MAX__ 0x7fff
+    #undef __linux__
+    #define __linux__ 1
+    #undef __INT64_TYPE__
+    #define __INT64_TYPE__ long long int
+    #undef __FLT_MAX_EXP__
+    #define __FLT_MAX_EXP__ 128
+    #undef __DBL_MANT_DIG__
+    #define __DBL_MANT_DIG__ 53
+    #undef __SIZEOF_FLOAT128__
+    #define __SIZEOF_FLOAT128__ 16
+    #undef __INT_LEAST64_MAX__
+    #define __INT_LEAST64_MAX__ 0x7fffffffffffffffLL
+    #undef __GCC_ATOMIC_CHAR16_T_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
+    #undef __DEC64_MIN__
+    #define __DEC64_MIN__ 1E-383DD
+    #undef __WINT_TYPE__
+    #define __WINT_TYPE__ unsigned long
+    #undef __UINT_LEAST32_TYPE__
+    #define __UINT_LEAST32_TYPE__ unsigned long
+    #undef __SIZEOF_SHORT__
+    #define __SIZEOF_SHORT__ 2
+    #undef __FLT32_NORM_MAX__
+    #define __FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32
+    #undef __SSE__
+    #define __SSE__ 1
+    #undef __LDBL_MIN_EXP__
+    #define __LDBL_MIN_EXP__ (-16381)
+    #undef __FLT64_MAX__
+    #define __FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64
+    #undef __WINT_WIDTH__
+    #define __WINT_WIDTH__ 32
+    #undef __INT_LEAST8_MAX__
+    #define __INT_LEAST8_MAX__ 0x7f
+    #undef __INT_LEAST64_WIDTH__
+    #define __INT_LEAST64_WIDTH__ 64
+    #undef __LDBL_MAX_EXP__
+    #define __LDBL_MAX_EXP__ 16384
+    #undef __FLT32X_MAX_10_EXP__
+    #define __FLT32X_MAX_10_EXP__ 308
+    #undef __FLT16_MIN__
+    #define __FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16
+    #undef __FLT64X_IS_IEC_60559__
+    #define __FLT64X_IS_IEC_60559__ 2
+    #undef __LDBL_MAX_10_EXP__
+    #define __LDBL_MAX_10_EXP__ 4932
+    #undef __ATOMIC_RELAXED
+    #define __ATOMIC_RELAXED 0
+    #undef __DBL_EPSILON__
+    #define __DBL_EPSILON__ ((double)2.22044604925031308084726333618164062e-16L)
+    #undef __FLT128_MIN__
+    #define __FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128
+    #undef __UINT8_C
+    #define __UINT8_C(c) c
+    #undef __FLT64_MAX_EXP__
+    #define __FLT64_MAX_EXP__ 1024
+    #undef __INT_LEAST32_TYPE__
+    #define __INT_LEAST32_TYPE__ long
+    #undef __SIZEOF_WCHAR_T__
+    #define __SIZEOF_WCHAR_T__ 2
+    #undef __UINT64_TYPE__
+    #define __UINT64_TYPE__ long long unsigned int
+    #undef __GNUC_PATCHLEVEL__
+    #define __GNUC_PATCHLEVEL__ 1
+    #undef __FLT128_NORM_MAX__
+    #define __FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128
+    #undef __FLT64_NORM_MAX__
+    #define __FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64
+    #undef __FLT128_HAS_QUIET_NAN__
+    #define __FLT128_HAS_QUIET_NAN__ 1
+    #undef __INTMAX_MAX__
+    #define __INTMAX_MAX__ 0x7fffffffffffffffLL
+    #undef __INT_FAST8_TYPE__
+    #define __INT_FAST8_TYPE__ signed char
+    #undef __FLT64X_MIN__
+    #define __FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x
+    #undef __GNUC_STDC_INLINE__
+    #define __GNUC_STDC_INLINE__ 1
+    #undef __FLT64_HAS_DENORM__
+    #define __FLT64_HAS_DENORM__ 1
+    #undef __FLT32_EPSILON__
+    #define __FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32
+    #undef __FLT16_HAS_DENORM__
+    #define __FLT16_HAS_DENORM__ 1
+    #undef __DBL_DECIMAL_DIG__
+    #define __DBL_DECIMAL_DIG__ 17
+    #undef __INT_FAST8_WIDTH__
+    #define __INT_FAST8_WIDTH__ 8
+    #undef __FXSR__
+    #define __FXSR__ 1
+    #undef __FLT32X_MAX__
+    #define __FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x
+    #undef __DBL_NORM_MAX__
+    #define __DBL_NORM_MAX__ ((double)1.79769313486231570814527423731704357e+308L)
+    #undef __BYTE_ORDER__
+    #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+    #undef __GCC_DESTRUCTIVE_SIZE
+    #define __GCC_DESTRUCTIVE_SIZE 64
+    #undef __INTMAX_WIDTH__
+    #define __INTMAX_WIDTH__ 64
+    #undef __ORDER_BIG_ENDIAN__
+    #define __ORDER_BIG_ENDIAN__ 4321
+    #undef __UINT32_C
+    #define __UINT32_C(c) c ## UL
+    #undef __FLT_DENORM_MIN__
+    #define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F
+    #undef __INT8_MAX__
+    #define __INT8_MAX__ 0x7f
+    #undef __LONG_WIDTH__
+    #define __LONG_WIDTH__ 32
+    #undef __PIC__
+    #define __PIC__ 2
+    #undef __UINT_FAST32_TYPE__
+    #define __UINT_FAST32_TYPE__ unsigned long
+    #undef __FLT32X_NORM_MAX__
+    #define __FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x
+    #undef __CHAR32_TYPE__
+    #define __CHAR32_TYPE__ unsigned long
+    #undef __FLT_MAX__
+    #define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F
+    #undef __SSE2__
+    #define __SSE2__ 1
+    #undef __INT32_TYPE__
+    #define __INT32_TYPE__ long
+    #undef __SIZEOF_DOUBLE__
+    #define __SIZEOF_DOUBLE__ 8
+    #undef __FLT_MIN_10_EXP__
+    #define __FLT_MIN_10_EXP__ (-37)
+    #undef __FLT64_MIN__
+    #define __FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64
+    #undef __INT_LEAST32_WIDTH__
+    #define __INT_LEAST32_WIDTH__ 32
+    #undef __INTMAX_TYPE__
+    #define __INTMAX_TYPE__ long long int
+    #undef __DEC128_MAX_EXP__
+    #define __DEC128_MAX_EXP__ 6145
+    #undef __FLT32X_HAS_QUIET_NAN__
+    #define __FLT32X_HAS_QUIET_NAN__ 1
+    #undef __ATOMIC_CONSUME
+    #define __ATOMIC_CONSUME 1
+    #undef __GNUC_MINOR__
+    #define __GNUC_MINOR__ 2
+    #undef __INT_FAST16_WIDTH__
+    #define __INT_FAST16_WIDTH__ 32
+    #undef __UINTMAX_MAX__
+    #define __UINTMAX_MAX__ 0xffffffffffffffffULL
+    #undef __PIE__
+    #define __PIE__ 2
+    #undef __FLT32X_DENORM_MIN__
+    #define __FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x
+    #undef __DBL_MAX_10_EXP__
+    #define __DBL_MAX_10_EXP__ 308
+    #undef __LDBL_DENORM_MIN__
+    #define __LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L
+    #undef __INT16_C
+    #define __INT16_C(c) c
+    #undef __PTRDIFF_TYPE__
+    #define __PTRDIFF_TYPE__ int
+    #undef __ATOMIC_SEQ_CST
+    #define __ATOMIC_SEQ_CST 5
+    #undef __FLT32X_MIN_10_EXP__
+    #define __FLT32X_MIN_10_EXP__ (-307)
+    #undef __UINTPTR_TYPE__
+    #define __UINTPTR_TYPE__ unsigned int
+    #undef __DEC64_SUBNORMAL_MIN__
+    #define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
+    #undef __DEC128_MANT_DIG__
+    #define __DEC128_MANT_DIG__ 34
+    #undef __LDBL_MIN_10_EXP__
+    #define __LDBL_MIN_10_EXP__ (-4931)
+    #undef __SIZEOF_LONG_LONG__
+    #define __SIZEOF_LONG_LONG__ 8
+    #undef __FLT128_DECIMAL_DIG__
+    #define __FLT128_DECIMAL_DIG__ 36
+    #undef __GCC_ATOMIC_LLONG_LOCK_FREE
+    #define __GCC_ATOMIC_LLONG_LOCK_FREE 2
+    #undef __FLT32_HAS_QUIET_NAN__
+    #define __FLT32_HAS_QUIET_NAN__ 1
+    #undef __FLT_DECIMAL_DIG__
+    #define __FLT_DECIMAL_DIG__ 9
+    #undef __UINT_FAST16_MAX__
+    #define __UINT_FAST16_MAX__ 0xffffU
+    #undef __LDBL_NORM_MAX__
+    #define __LDBL_NORM_MAX__ 1.18973149535723176502126385303097021e+4932L
+    #undef __GCC_ATOMIC_SHORT_LOCK_FREE
+    #define __GCC_ATOMIC_SHORT_LOCK_FREE 2
+    #undef __UINT_FAST8_TYPE__
+    #define __UINT_FAST8_TYPE__ unsigned char
+    #undef __ATOMIC_ACQ_REL
+    #define __ATOMIC_ACQ_REL 4
+    #undef __ATOMIC_RELEASE
+    #define __ATOMIC_RELEASE 3
+
+errno:
+    e2big: '7'
+    eacces: '13'
+    eaddrinuse: '98'
+    eaddrnotavail: '99'
+    eafnosupport: '97'
+    eagain: '11'
+    ealready: '114'
+    ebade: '52'
+    ebadf: '9'
+    ebadfd: '77'
+    ebadmsg: '74'
+    ebadr: '53'
+    ebadrqc: '56'
+    ebadslt: '57'
+    ebusy: '16'
+    ecanceled: '125'
+    echild: '10'
+    echrng: '44'
+    ecomm: '70'
+    econnaborted: '103'
+    econnrefused: '111'
+    econnreset: '104'
+    edeadlk: '35'
+    edeadlock: '35'
+    edestaddrreq: '89'
+    edom: '33'
+    edquot: '122'
+    eexist: '17'
+    efault: '14'
+    efbig: '27'
+    ehostdown: '112'
+    ehostunreach: '113'
+    eidrm: '43'
+    eilseq: '84'
+    einprogress: '115'
+    eintr: '4'
+    einval: '22'
+    eio: '5'
+    eisconn: '106'
+    eisdir: '21'
+    eisnam: '120'
+    ekeyexpired: '127'
+    ekeyrejected: '129'
+    ekeyrevoked: '128'
+    el2hlt: '51'
+    el2nsync: '45'
+    el3hlt: '46'
+    el3rst: '47'
+    elibacc: '79'
+    elibbad: '80'
+    elibexec: '83'
+    elibmax: '82'
+    elibscn: '81'
+    eloop: '40'
+    emediumtype: '124'
+    emfile: '24'
+    emlink: '31'
+    emsgsize: '90'
+    emultihop: '72'
+    enametoolong: '36'
+    enetdown: '100'
+    enetreset: '102'
+    enetunreach: '101'
+    enfile: '23'
+    enobufs: '105'
+    enodata: '61'
+    enodev: '19'
+    enoent: '2'
+    enoexec: '8'
+    enokey: '126'
+    enolck: '37'
+    enolink: '67'
+    enomedium: '123'
+    enomem: '12'
+    enomsg: '42'
+    enonet: '64'
+    enopkg: '65'
+    enoprotoopt: '92'
+    enospc: '28'
+    enosr: '63'
+    enostr: '60'
+    enosys: '38'
+    enotblk: '15'
+    enotconn: '107'
+    enotdir: '20'
+    enotempty: '39'
+    enotrecoverable: '131'
+    enotsock: '88'
+    enotsup: '95'
+    enotty: '25'
+    enotuniq: '76'
+    enxio: '6'
+    eopnotsupp: '95'
+    eoverflow: '75'
+    eownerdead: '130'
+    eperm: '1'
+    epfnosupport: '96'
+    epipe: '32'
+    eproto: '71'
+    eprotonosupport: '93'
+    eprototype: '91'
+    erange: '34'
+    eremchg: '78'
+    eremote: '66'
+    eremoteio: '121'
+    erestart: '85'
+    erofs: '30'
+    eshutdown: '108'
+    esocktnosupport: '94'
+    espipe: '29'
+    esrch: '3'
+    estale: '116'
+    estrpipe: '86'
+    etime: '62'
+    etimedout: '110'
+    etxtbsy: '26'
+    euclean: '117'
+    eunatch: '49'
+    eusers: '87'
+    ewouldblock: '11'
+    exdev: '18'
+    exfull: '54'
+has__builtin_va_list: true
+int_fast8_t: signed char
+int_fast16_t: signed int
+int_fast32_t: long
+int_fast64_t: long long
+intptr_t: long
+little_endian: true
+nsig: '65'
+ptrdiff_t: int
+sig_atomic_t: int
+size_t: unsigned int
+sizeof_double: 8
+sizeof_float: 4
+sizeof_fun: 1
+sizeof_int: 2
+sizeof_long: 4
+sizeof_longdouble: 16
+sizeof_longlong: 8
+sizeof_ptr: 4
+sizeof_short: 2
+sizeof_void: 1
+ssize_t: int
+time_t: long
+uint_fast8_t: unsigned char
+uint_fast16_t: unsigned int
+uint_fast32_t: unsigned long
+uint_fast64_t: unsigned long long
+uintptr_t: unsigned long
+version: none
+wchar_t: int
+weof: (0xffffffffUL)
+wint_t: unsigned long
+wordsize: '16'
+posix_version: '200809L'
+bufsiz: '8192'
+eof: '(-1)'
+fopen_max: '16'
+filename_max: '2048'
+path_max: '256'
+host_name_max: '64'
+tty_name_max: '32'
+l_tmpnam: '2048'
+tmp_max: '0xFFFFFFFF'
+rand_max: '32767'
+mb_cur_max: '((size_t)16)'
+machdep_name: machdep_gcc_x86_16
diff --git a/share/machdeps/machdep_gcc_x86_32.yaml b/share/machdeps/machdep_gcc_x86_32.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..09ad500596d56e7f598c51c524221615a08a9a67
--- /dev/null
+++ b/share/machdeps/machdep_gcc_x86_32.yaml
@@ -0,0 +1,957 @@
+alignof_aligned: 16
+alignof_double: 4
+alignof_float: 4
+alignof_fun: 1
+alignof_int: 4
+alignof_long: 4
+alignof_longdouble: 4
+alignof_longlong: 4
+alignof_ptr: 4
+alignof_short: 2
+alignof_str: 1
+bufsiz: '8192'
+char_is_unsigned: false
+compiler: gcc
+cpp_arch_flags:
+- -m32
+custom_defs: |
+    #undef __DBL_MIN_EXP__
+    #define __DBL_MIN_EXP__ (-1021)
+    #undef __UINT_LEAST16_MAX__
+    #define __UINT_LEAST16_MAX__ 0xffff
+    #undef __FLT16_HAS_QUIET_NAN__
+    #define __FLT16_HAS_QUIET_NAN__ 1
+    #undef __ATOMIC_ACQUIRE
+    #define __ATOMIC_ACQUIRE 2
+    #undef __FLT128_MAX_10_EXP__
+    #define __FLT128_MAX_10_EXP__ 4932
+    #undef __FLT_MIN__
+    #define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F
+    #undef __GCC_IEC_559_COMPLEX
+    #define __GCC_IEC_559_COMPLEX 2
+    #undef __UINT_LEAST8_TYPE__
+    #define __UINT_LEAST8_TYPE__ unsigned char
+    #undef __SIZEOF_FLOAT80__
+    #define __SIZEOF_FLOAT80__ 12
+    #undef __BFLT16_DENORM_MIN__
+    #define __BFLT16_DENORM_MIN__ 9.18354961579912115600575419704879436e-41BF16
+    #undef __INTMAX_C
+    #define __INTMAX_C(c) c ## LL
+    #undef __CHAR_BIT__
+    #define __CHAR_BIT__ 8
+    #undef __UINT8_MAX__
+    #define __UINT8_MAX__ 0xff
+    #undef __SCHAR_WIDTH__
+    #define __SCHAR_WIDTH__ 8
+    #undef __WINT_MAX__
+    #define __WINT_MAX__ 0xffffffffU
+    #undef __FLT32_MIN_EXP__
+    #define __FLT32_MIN_EXP__ (-125)
+    #undef __BFLT16_NORM_MAX__
+    #define __BFLT16_NORM_MAX__ 3.38953138925153547590470800371487867e+38BF16
+    #undef __BFLT16_MIN_10_EXP__
+    #define __BFLT16_MIN_10_EXP__ (-37)
+    #undef __ORDER_LITTLE_ENDIAN__
+    #define __ORDER_LITTLE_ENDIAN__ 1234
+    #undef __WCHAR_MAX__
+    #define __WCHAR_MAX__ 0x7fffffffL
+    #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
+    #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
+    #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
+    #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
+    #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
+    #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
+    #undef __GCC_ATOMIC_CHAR_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR_LOCK_FREE 2
+    #undef __GCC_IEC_559
+    #define __GCC_IEC_559 2
+    #undef __FLT32X_DECIMAL_DIG__
+    #define __FLT32X_DECIMAL_DIG__ 17
+    #undef __FLT_EVAL_METHOD__
+    #define __FLT_EVAL_METHOD__ 2
+    #undef __FLT64_DECIMAL_DIG__
+    #define __FLT64_DECIMAL_DIG__ 17
+    #undef __GCC_ATOMIC_CHAR32_T_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
+    #undef __UINT_FAST64_MAX__
+    #define __UINT_FAST64_MAX__ 0xffffffffffffffffULL
+    #undef __SIG_ATOMIC_TYPE__
+    #define __SIG_ATOMIC_TYPE__ int
+    #undef __DBL_MIN_10_EXP__
+    #define __DBL_MIN_10_EXP__ (-307)
+    #undef __FINITE_MATH_ONLY__
+    #define __FINITE_MATH_ONLY__ 0
+    #undef __FLT32X_MAX_EXP__
+    #define __FLT32X_MAX_EXP__ 1024
+    #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
+    #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+    #undef __FLT32_HAS_DENORM__
+    #define __FLT32_HAS_DENORM__ 1
+    #undef __UINT_FAST8_MAX__
+    #define __UINT_FAST8_MAX__ 0xff
+    #undef __FLT32_MAX_10_EXP__
+    #define __FLT32_MAX_10_EXP__ 38
+    #undef __DEC64_MAX_EXP__
+    #define __DEC64_MAX_EXP__ 385
+    #undef __INT8_C
+    #define __INT8_C(c) c
+    #undef __INT_LEAST8_WIDTH__
+    #define __INT_LEAST8_WIDTH__ 8
+    #undef __UINT_LEAST64_MAX__
+    #define __UINT_LEAST64_MAX__ 0xffffffffffffffffULL
+    #undef __SHRT_MAX__
+    #define __SHRT_MAX__ 0x7fff
+    #undef __LDBL_MAX__
+    #define __LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L
+    #undef __FLT64X_MAX_10_EXP__
+    #define __FLT64X_MAX_10_EXP__ 4932
+    #undef __BFLT16_MAX_10_EXP__
+    #define __BFLT16_MAX_10_EXP__ 38
+    #undef __BFLT16_MAX_EXP__
+    #define __BFLT16_MAX_EXP__ 128
+    #undef __LDBL_IS_IEC_60559__
+    #define __LDBL_IS_IEC_60559__ 1
+    #undef __FLT64X_HAS_QUIET_NAN__
+    #define __FLT64X_HAS_QUIET_NAN__ 1
+    #undef __UINT_LEAST8_MAX__
+    #define __UINT_LEAST8_MAX__ 0xff
+    #undef __GCC_ATOMIC_BOOL_LOCK_FREE
+    #define __GCC_ATOMIC_BOOL_LOCK_FREE 2
+    #undef __LAHF_SAHF__
+    #define __LAHF_SAHF__ 1
+    #undef __FLT128_DENORM_MIN__
+    #define __FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128
+    #undef __UINTMAX_TYPE__
+    #define __UINTMAX_TYPE__ long long unsigned int
+    #undef __BFLT16_DECIMAL_DIG__
+    #define __BFLT16_DECIMAL_DIG__ 4
+    #undef __linux
+    #define __linux 1
+    #undef __DEC32_EPSILON__
+    #define __DEC32_EPSILON__ 1E-6DF
+    #undef __FLT_EVAL_METHOD_TS_18661_3__
+    #define __FLT_EVAL_METHOD_TS_18661_3__ 2
+    #undef __UINT32_MAX__
+    #define __UINT32_MAX__ 0xffffffffU
+    #undef __DBL_DENORM_MIN__
+    #define __DBL_DENORM_MIN__ ((double)4.94065645841246544176568792868221372e-324L)
+    #undef __FLT128_MIN_EXP__
+    #define __FLT128_MIN_EXP__ (-16381)
+    #undef __WINT_MIN__
+    #define __WINT_MIN__ 0U
+    #undef __FLT128_MIN_10_EXP__
+    #define __FLT128_MIN_10_EXP__ (-4931)
+    #undef __FLT32X_IS_IEC_60559__
+    #define __FLT32X_IS_IEC_60559__ 1
+    #undef __INT_LEAST16_WIDTH__
+    #define __INT_LEAST16_WIDTH__ 16
+    #undef __SCHAR_MAX__
+    #define __SCHAR_MAX__ 0x7f
+    #undef __FLT128_MANT_DIG__
+    #define __FLT128_MANT_DIG__ 113
+    #undef __WCHAR_MIN__
+    #define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
+    #undef __INT64_C
+    #define __INT64_C(c) c ## LL
+    #undef __SSP_STRONG__
+    #define __SSP_STRONG__ 3
+    #undef __GCC_ATOMIC_POINTER_LOCK_FREE
+    #define __GCC_ATOMIC_POINTER_LOCK_FREE 2
+    #undef __ATOMIC_SEQ_CST
+    #define __ATOMIC_SEQ_CST 5
+    #undef __unix
+    #define __unix 1
+    #undef __INT_LEAST64_MAX__
+    #define __INT_LEAST64_MAX__ 0x7fffffffffffffffLL
+    #undef __FLT32X_MANT_DIG__
+    #define __FLT32X_MANT_DIG__ 53
+    #undef __FLT64X_EPSILON__
+    #define __FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x
+    #undef __DEC64_MIN_EXP__
+    #define __DEC64_MIN_EXP__ (-382)
+    #undef __DBL_DIG__
+    #define __DBL_DIG__ 15
+    #undef __FLT_EPSILON__
+    #define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F
+    #undef __SHRT_WIDTH__
+    #define __SHRT_WIDTH__ 16
+    #undef __FLT32_IS_IEC_60559__
+    #define __FLT32_IS_IEC_60559__ 1
+    #undef __LDBL_MIN__
+    #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
+    #undef __DBL_IS_IEC_60559__
+    #define __DBL_IS_IEC_60559__ 1
+    #undef __DEC32_MAX__
+    #define __DEC32_MAX__ 9.999999E96DF
+    #undef __FLT64X_DENORM_MIN__
+    #define __FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x
+    #undef __FLT32X_HAS_INFINITY__
+    #define __FLT32X_HAS_INFINITY__ 1
+    #undef __unix__
+    #define __unix__ 1
+    #undef __INT_WIDTH__
+    #define __INT_WIDTH__ 32
+    #undef __DECIMAL_DIG__
+    #define __DECIMAL_DIG__ 21
+    #undef __FLT64_EPSILON__
+    #define __FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64
+    #undef __gnu_linux__
+    #define __gnu_linux__ 1
+    #undef __FLT128_IS_IEC_60559__
+    #define __FLT128_IS_IEC_60559__ 1
+    #undef __FLT64X_MIN_10_EXP__
+    #define __FLT64X_MIN_10_EXP__ (-4931)
+    #undef __LDBL_HAS_QUIET_NAN__
+    #define __LDBL_HAS_QUIET_NAN__ 1
+    #undef __FLT16_MIN_EXP__
+    #define __FLT16_MIN_EXP__ (-13)
+    #undef __FLT64_MANT_DIG__
+    #define __FLT64_MANT_DIG__ 53
+    #undef __FLT64X_MANT_DIG__
+    #define __FLT64X_MANT_DIG__ 64
+    #undef __BFLT16_DIG__
+    #define __BFLT16_DIG__ 2
+    #undef __GNUC__
+    #define __GNUC__ 13
+    #undef __pie__
+    #define __pie__ 2
+    #undef __MMX__
+    #define __MMX__ 1
+    #undef __FLT_HAS_DENORM__
+    #define __FLT_HAS_DENORM__ 1
+    #undef __SIZEOF_LONG_DOUBLE__
+    #define __SIZEOF_LONG_DOUBLE__ 12
+    #undef __BIGGEST_ALIGNMENT__
+    #define __BIGGEST_ALIGNMENT__ 16
+    #undef __FLT64_MAX_10_EXP__
+    #define __FLT64_MAX_10_EXP__ 308
+    #undef __BFLT16_IS_IEC_60559__
+    #define __BFLT16_IS_IEC_60559__ 0
+    #undef __FLT16_MAX_10_EXP__
+    #define __FLT16_MAX_10_EXP__ 4
+    #undef __DBL_MAX__
+    #define __DBL_MAX__ ((double)1.79769313486231570814527423731704357e+308L)
+    #undef __INT_FAST32_MAX__
+    #define __INT_FAST32_MAX__ 0x7fffffff
+    #undef __DBL_HAS_INFINITY__
+    #define __DBL_HAS_INFINITY__ 1
+    #undef __INT64_MAX__
+    #define __INT64_MAX__ 0x7fffffffffffffffLL
+    #undef __SIZEOF_FLOAT__
+    #define __SIZEOF_FLOAT__ 4
+    #undef __HAVE_SPECULATION_SAFE_VALUE
+    #define __HAVE_SPECULATION_SAFE_VALUE 1
+    #undef __DEC32_MIN_EXP__
+    #define __DEC32_MIN_EXP__ (-94)
+    #undef __INTPTR_WIDTH__
+    #define __INTPTR_WIDTH__ 32
+    #undef __UINT_LEAST32_MAX__
+    #define __UINT_LEAST32_MAX__ 0xffffffffU
+    #undef __FLT32X_HAS_DENORM__
+    #define __FLT32X_HAS_DENORM__ 1
+    #undef __INT_FAST16_TYPE__
+    #define __INT_FAST16_TYPE__ int
+    #undef __LDBL_HAS_DENORM__
+    #define __LDBL_HAS_DENORM__ 1
+    #undef __SEG_GS
+    #define __SEG_GS 1
+    #undef __BFLT16_EPSILON__
+    #define __BFLT16_EPSILON__ 7.81250000000000000000000000000000000e-3BF16
+    #undef __FLT128_HAS_INFINITY__
+    #define __FLT128_HAS_INFINITY__ 1
+    #undef __DEC32_MIN__
+    #define __DEC32_MIN__ 1E-95DF
+    #undef __DBL_MAX_EXP__
+    #define __DBL_MAX_EXP__ 1024
+    #undef __WCHAR_WIDTH__
+    #define __WCHAR_WIDTH__ 32
+    #undef __FLT32_MAX__
+    #define __FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32
+    #undef __DEC128_EPSILON__
+    #define __DEC128_EPSILON__ 1E-33DL
+    #undef __FLT16_DECIMAL_DIG__
+    #define __FLT16_DECIMAL_DIG__ 5
+    #undef __ATOMIC_HLE_RELEASE
+    #define __ATOMIC_HLE_RELEASE 131072
+    #undef __PTRDIFF_MAX__
+    #define __PTRDIFF_MAX__ 0x7fffffff
+    #undef __ATOMIC_HLE_ACQUIRE
+    #define __ATOMIC_HLE_ACQUIRE 65536
+    #undef __LONG_LONG_MAX__
+    #define __LONG_LONG_MAX__ 0x7fffffffffffffffLL
+    #undef __SIZEOF_SIZE_T__
+    #define __SIZEOF_SIZE_T__ 4
+    #undef __BFLT16_HAS_INFINITY__
+    #define __BFLT16_HAS_INFINITY__ 1
+    #undef __FLT64X_MIN_EXP__
+    #define __FLT64X_MIN_EXP__ (-16381)
+    #undef __SIZEOF_WINT_T__
+    #define __SIZEOF_WINT_T__ 4
+    #undef __LONG_LONG_WIDTH__
+    #define __LONG_LONG_WIDTH__ 64
+    #undef __FLT32_MAX_EXP__
+    #define __FLT32_MAX_EXP__ 128
+    #undef __GXX_ABI_VERSION
+    #define __GXX_ABI_VERSION 1018
+    #undef __FLT_MIN_EXP__
+    #define __FLT_MIN_EXP__ (-125)
+    #undef __GCC_HAVE_DWARF2_CFI_ASM
+    #define __GCC_HAVE_DWARF2_CFI_ASM 1
+    #undef __INT16_MAX__
+    #define __INT16_MAX__ 0x7fff
+    #undef __INT_FAST64_TYPE__
+    #define __INT_FAST64_TYPE__ long long int
+    #undef __BFLT16_MAX__
+    #define __BFLT16_MAX__ 3.38953138925153547590470800371487867e+38BF16
+    #undef __BFLT16_HAS_DENORM__
+    #define __BFLT16_HAS_DENORM__ 1
+    #undef __FLT64_DENORM_MIN__
+    #define __FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64
+    #undef __FLT16_DENORM_MIN__
+    #define __FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16
+    #undef __FLT128_EPSILON__
+    #define __FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128
+    #undef __FLT64X_NORM_MAX__
+    #define __FLT64X_NORM_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+    #undef __SIZEOF_POINTER__
+    #define __SIZEOF_POINTER__ 4
+    #undef __SIZE_TYPE__
+    #define __SIZE_TYPE__ unsigned int
+    #undef __DBL_HAS_QUIET_NAN__
+    #define __DBL_HAS_QUIET_NAN__ 1
+    #undef __FLT32X_EPSILON__
+    #define __FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x
+    #undef __LDBL_MAX_EXP__
+    #define __LDBL_MAX_EXP__ 16384
+    #undef __DECIMAL_BID_FORMAT__
+    #define __DECIMAL_BID_FORMAT__ 1
+    #undef __FLT64_MIN_EXP__
+    #define __FLT64_MIN_EXP__ (-1021)
+    #undef __FLT64_MIN_10_EXP__
+    #define __FLT64_MIN_10_EXP__ (-307)
+    #undef __FLT16_MIN_10_EXP__
+    #define __FLT16_MIN_10_EXP__ (-4)
+    #undef __FLT64X_DECIMAL_DIG__
+    #define __FLT64X_DECIMAL_DIG__ 21
+    #undef __DEC128_MIN__
+    #define __DEC128_MIN__ 1E-6143DL
+    #undef __REGISTER_PREFIX__
+    #define __REGISTER_PREFIX__
+    #undef __UINT16_MAX__
+    #define __UINT16_MAX__ 0xffff
+    #undef __DBL_HAS_DENORM__
+    #define __DBL_HAS_DENORM__ 1
+    #undef __FLT32_MIN__
+    #define __FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32
+    #undef __UINT8_TYPE__
+    #define __UINT8_TYPE__ unsigned char
+    #undef __FLT_DIG__
+    #define __FLT_DIG__ 6
+    #undef __NO_INLINE__
+    #define __NO_INLINE__ 1
+    #undef __DEC_EVAL_METHOD__
+    #define __DEC_EVAL_METHOD__ 2
+    #undef __i386
+    #define __i386 1
+    #undef __FLT_MANT_DIG__
+    #define __FLT_MANT_DIG__ 24
+    #undef __LDBL_DECIMAL_DIG__
+    #define __LDBL_DECIMAL_DIG__ 21
+    #undef __VERSION__
+    #define __VERSION__ "13.1.1 20230429"
+    #undef __UINT64_C
+    #define __UINT64_C(c) c ## ULL
+    #undef _STDC_PREDEF_H
+    #define _STDC_PREDEF_H 1
+    #undef __INT_LEAST32_MAX__
+    #define __INT_LEAST32_MAX__ 0x7fffffff
+    #undef __GCC_ATOMIC_INT_LOCK_FREE
+    #define __GCC_ATOMIC_INT_LOCK_FREE 2
+    #undef __FLT128_MAX_EXP__
+    #define __FLT128_MAX_EXP__ 16384
+    #undef __FLT32_MANT_DIG__
+    #define __FLT32_MANT_DIG__ 24
+    #undef __FLOAT_WORD_ORDER__
+    #define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
+    #undef __FLT32X_MIN_EXP__
+    #define __FLT32X_MIN_EXP__ (-1021)
+    #undef i386
+    #define i386 1
+    #undef __BFLT16_MIN__
+    #define __BFLT16_MIN__ 1.17549435082228750796873653722224568e-38BF16
+    #undef __FLT128_HAS_DENORM__
+    #define __FLT128_HAS_DENORM__ 1
+    #undef __FLT32_DECIMAL_DIG__
+    #define __FLT32_DECIMAL_DIG__ 9
+    #undef __FLT128_DIG__
+    #define __FLT128_DIG__ 33
+    #undef __INT32_C
+    #define __INT32_C(c) c
+    #undef __DEC64_EPSILON__
+    #define __DEC64_EPSILON__ 1E-15DD
+    #undef __ORDER_PDP_ENDIAN__
+    #define __ORDER_PDP_ENDIAN__ 3412
+    #undef __DEC128_MIN_EXP__
+    #define __DEC128_MIN_EXP__ (-6142)
+    #undef __code_model_32__
+    #define __code_model_32__ 1
+    #undef __DEC128_MAX__
+    #define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
+    #undef __INT_FAST32_TYPE__
+    #define __INT_FAST32_TYPE__ int
+    #undef __UINT_LEAST16_TYPE__
+    #define __UINT_LEAST16_TYPE__ short unsigned int
+    #undef __DEC128_MAX_EXP__
+    #define __DEC128_MAX_EXP__ 6145
+    #undef unix
+    #define unix 1
+    #undef __i386__
+    #define __i386__ 1
+    #undef __UINT64_MAX__
+    #define __UINT64_MAX__ 0xffffffffffffffffULL
+    #undef __FLT_IS_IEC_60559__
+    #define __FLT_IS_IEC_60559__ 1
+    #undef __GNUC_WIDE_EXECUTION_CHARSET_NAME
+    #define __GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE"
+    #undef __FLT64X_DIG__
+    #define __FLT64X_DIG__ 18
+    #undef __INT8_TYPE__
+    #define __INT8_TYPE__ signed char
+    #undef __ELF__
+    #define __ELF__ 1
+    #undef __GCC_ASM_FLAG_OUTPUTS__
+    #define __GCC_ASM_FLAG_OUTPUTS__ 1
+    #undef __UINT32_TYPE__
+    #define __UINT32_TYPE__ unsigned int
+    #undef __BFLT16_HAS_QUIET_NAN__
+    #define __BFLT16_HAS_QUIET_NAN__ 1
+    #undef __FLT_RADIX__
+    #define __FLT_RADIX__ 2
+    #undef __INT_LEAST16_TYPE__
+    #define __INT_LEAST16_TYPE__ short int
+    #undef __LDBL_EPSILON__
+    #define __LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L
+    #undef __UINTMAX_C
+    #define __UINTMAX_C(c) c ## ULL
+    #undef __FLT16_DIG__
+    #define __FLT16_DIG__ 3
+    #undef __k8
+    #define __k8 1
+    #undef __FLT32X_MIN__
+    #define __FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x
+    #undef __SIG_ATOMIC_MAX__
+    #define __SIG_ATOMIC_MAX__ 0x7fffffff
+    #undef __GCC_ATOMIC_WCHAR_T_LOCK_FREE
+    #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
+    #undef __USER_LABEL_PREFIX__
+    #define __USER_LABEL_PREFIX__
+    #undef __SIZEOF_PTRDIFF_T__
+    #define __SIZEOF_PTRDIFF_T__ 4
+    #undef __FLT64X_HAS_INFINITY__
+    #define __FLT64X_HAS_INFINITY__ 1
+    #undef __FLT32_HAS_INFINITY__
+    #define __FLT32_HAS_INFINITY__ 1
+    #undef __SIZEOF_LONG__
+    #define __SIZEOF_LONG__ 4
+    #undef __LDBL_DIG__
+    #define __LDBL_DIG__ 18
+    #undef __FLT64_IS_IEC_60559__
+    #define __FLT64_IS_IEC_60559__ 1
+    #undef __FLT16_IS_IEC_60559__
+    #define __FLT16_IS_IEC_60559__ 1
+    #undef __FLT16_MAX_EXP__
+    #define __FLT16_MAX_EXP__ 16
+    #undef __DEC32_SUBNORMAL_MIN__
+    #define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
+    #undef __INT_FAST16_MAX__
+    #define __INT_FAST16_MAX__ 0x7fffffff
+    #undef __GCC_CONSTRUCTIVE_SIZE
+    #define __GCC_CONSTRUCTIVE_SIZE 64
+    #undef __FLT64_DIG__
+    #define __FLT64_DIG__ 15
+    #undef __UINT_FAST32_MAX__
+    #define __UINT_FAST32_MAX__ 0xffffffffU
+    #undef __UINT_LEAST64_TYPE__
+    #define __UINT_LEAST64_TYPE__ long long unsigned int
+    #undef __FLT16_EPSILON__
+    #define __FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16
+    #undef __ILP32__
+    #define __ILP32__ 1
+    #undef __FLT_HAS_QUIET_NAN__
+    #define __FLT_HAS_QUIET_NAN__ 1
+    #undef __FLT_MAX_10_EXP__
+    #define __FLT_MAX_10_EXP__ 38
+    #undef __LONG_MAX__
+    #define __LONG_MAX__ 0x7fffffffL
+    #undef __FLT64X_HAS_DENORM__
+    #define __FLT64X_HAS_DENORM__ 1
+    #undef __DEC128_SUBNORMAL_MIN__
+    #define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
+    #undef __FLT_HAS_INFINITY__
+    #define __FLT_HAS_INFINITY__ 1
+    #undef __GNUC_EXECUTION_CHARSET_NAME
+    #define __GNUC_EXECUTION_CHARSET_NAME "UTF-8"
+    #undef _ILP32
+    #define _ILP32 1
+    #undef __UINT_FAST16_TYPE__
+    #define __UINT_FAST16_TYPE__ unsigned int
+    #undef __DEC64_MAX__
+    #define __DEC64_MAX__ 9.999999999999999E384DD
+    #undef __INT_FAST32_WIDTH__
+    #define __INT_FAST32_WIDTH__ 32
+    #undef __CHAR16_TYPE__
+    #define __CHAR16_TYPE__ short unsigned int
+    #undef __PRAGMA_REDEFINE_EXTNAME
+    #define __PRAGMA_REDEFINE_EXTNAME 1
+    #undef __SIZE_WIDTH__
+    #define __SIZE_WIDTH__ 32
+    #undef __SEG_FS
+    #define __SEG_FS 1
+    #undef __INT_LEAST16_MAX__
+    #define __INT_LEAST16_MAX__ 0x7fff
+    #undef __FLT16_NORM_MAX__
+    #define __FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16
+    #undef __DEC64_MANT_DIG__
+    #define __DEC64_MANT_DIG__ 16
+    #undef __FLT32_DENORM_MIN__
+    #define __FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32
+    #undef __SIG_ATOMIC_WIDTH__
+    #define __SIG_ATOMIC_WIDTH__ 32
+    #undef __INT_LEAST64_TYPE__
+    #define __INT_LEAST64_TYPE__ long long int
+    #undef __INT16_TYPE__
+    #define __INT16_TYPE__ short int
+    #undef __INT_LEAST8_TYPE__
+    #define __INT_LEAST8_TYPE__ signed char
+    #undef __FLT16_MAX__
+    #define __FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16
+    #undef __FLT128_MIN__
+    #define __FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128
+    #undef __SIZEOF_INT__
+    #define __SIZEOF_INT__ 4
+    #undef __DEC32_MAX_EXP__
+    #define __DEC32_MAX_EXP__ 97
+    #undef __INT_FAST8_MAX__
+    #define __INT_FAST8_MAX__ 0x7f
+    #undef __FLT128_MAX__
+    #define __FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128
+    #undef __INTPTR_MAX__
+    #define __INTPTR_MAX__ 0x7fffffff
+    #undef linux
+    #define linux 1
+    #undef __FLT64_HAS_QUIET_NAN__
+    #define __FLT64_HAS_QUIET_NAN__ 1
+    #undef __FLT32_MIN_10_EXP__
+    #define __FLT32_MIN_10_EXP__ (-37)
+    #undef __FLT32X_DIG__
+    #define __FLT32X_DIG__ 15
+    #undef __UINT16_C
+    #define __UINT16_C(c) c
+    #undef __PTRDIFF_WIDTH__
+    #define __PTRDIFF_WIDTH__ 32
+    #undef __LDBL_MANT_DIG__
+    #define __LDBL_MANT_DIG__ 64
+    #undef __INT_FAST16_WIDTH__
+    #define __INT_FAST16_WIDTH__ 32
+    #undef __FLT64_HAS_INFINITY__
+    #define __FLT64_HAS_INFINITY__ 1
+    #undef __FLT64X_MAX__
+    #define __FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+    #undef __FLT16_HAS_INFINITY__
+    #define __FLT16_HAS_INFINITY__ 1
+    #undef __SIG_ATOMIC_MIN__
+    #define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
+    #undef __GCC_ATOMIC_LONG_LOCK_FREE
+    #define __GCC_ATOMIC_LONG_LOCK_FREE 2
+    #undef __DEC32_MANT_DIG__
+    #define __DEC32_MANT_DIG__ 7
+    #undef __FLT16_MANT_DIG__
+    #define __FLT16_MANT_DIG__ 11
+    #undef __k8__
+    #define __k8__ 1
+    #undef __INTPTR_TYPE__
+    #define __INTPTR_TYPE__ int
+    #undef __UINT16_TYPE__
+    #define __UINT16_TYPE__ short unsigned int
+    #undef __WCHAR_TYPE__
+    #define __WCHAR_TYPE__ long int
+    #undef __pic__
+    #define __pic__ 2
+    #undef __UINTPTR_MAX__
+    #define __UINTPTR_MAX__ 0xffffffffU
+    #undef __INT_FAST64_WIDTH__
+    #define __INT_FAST64_WIDTH__ 64
+    #undef __LDBL_HAS_INFINITY__
+    #define __LDBL_HAS_INFINITY__ 1
+    #undef __INT_FAST64_MAX__
+    #define __INT_FAST64_MAX__ 0x7fffffffffffffffLL
+    #undef __GCC_ATOMIC_TEST_AND_SET_TRUEVAL
+    #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
+    #undef __FLT_NORM_MAX__
+    #define __FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F
+    #undef __FLT64X_MAX_EXP__
+    #define __FLT64X_MAX_EXP__ 16384
+    #undef __UINT_FAST64_TYPE__
+    #define __UINT_FAST64_TYPE__ long long unsigned int
+    #undef __BFLT16_MIN_EXP__
+    #define __BFLT16_MIN_EXP__ (-125)
+    #undef __INT_MAX__
+    #define __INT_MAX__ 0x7fffffff
+    #undef __linux__
+    #define __linux__ 1
+    #undef __INT64_TYPE__
+    #define __INT64_TYPE__ long long int
+    #undef __FLT_MAX_EXP__
+    #define __FLT_MAX_EXP__ 128
+    #undef __DBL_MANT_DIG__
+    #define __DBL_MANT_DIG__ 53
+    #undef __SIZEOF_FLOAT128__
+    #define __SIZEOF_FLOAT128__ 16
+    #undef __BFLT16_MANT_DIG__
+    #define __BFLT16_MANT_DIG__ 8
+    #undef __GCC_ATOMIC_CHAR16_T_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
+    #undef __DEC64_MIN__
+    #define __DEC64_MIN__ 1E-383DD
+    #undef __WINT_TYPE__
+    #define __WINT_TYPE__ unsigned int
+    #undef __UINT_LEAST32_TYPE__
+    #define __UINT_LEAST32_TYPE__ unsigned int
+    #undef __SIZEOF_SHORT__
+    #define __SIZEOF_SHORT__ 2
+    #undef __FLT32_NORM_MAX__
+    #define __FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32
+    #undef __SSE__
+    #define __SSE__ 1
+    #undef __LDBL_MIN_EXP__
+    #define __LDBL_MIN_EXP__ (-16381)
+    #undef __FLT64_MAX__
+    #define __FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64
+    #undef __WINT_WIDTH__
+    #define __WINT_WIDTH__ 32
+    #undef __INT_LEAST8_MAX__
+    #define __INT_LEAST8_MAX__ 0x7f
+    #undef __INT_LEAST64_WIDTH__
+    #define __INT_LEAST64_WIDTH__ 64
+    #undef __FLT32X_MAX_10_EXP__
+    #define __FLT32X_MAX_10_EXP__ 308
+    #undef __FLT16_MIN__
+    #define __FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16
+    #undef __FLT64X_IS_IEC_60559__
+    #define __FLT64X_IS_IEC_60559__ 1
+    #undef __LDBL_MAX_10_EXP__
+    #define __LDBL_MAX_10_EXP__ 4932
+    #undef __ATOMIC_RELAXED
+    #define __ATOMIC_RELAXED 0
+    #undef __DBL_EPSILON__
+    #define __DBL_EPSILON__ ((double)2.22044604925031308084726333618164062e-16L)
+    #undef __INT_LEAST32_TYPE__
+    #define __INT_LEAST32_TYPE__ int
+    #undef __UINT8_C
+    #define __UINT8_C(c) c
+    #undef __FLT64_MAX_EXP__
+    #define __FLT64_MAX_EXP__ 1024
+    #undef __SIZEOF_WCHAR_T__
+    #define __SIZEOF_WCHAR_T__ 4
+    #undef __UINT64_TYPE__
+    #define __UINT64_TYPE__ long long unsigned int
+    #undef __GNUC_PATCHLEVEL__
+    #define __GNUC_PATCHLEVEL__ 1
+    #undef __FLT128_NORM_MAX__
+    #define __FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128
+    #undef __FLT64_NORM_MAX__
+    #define __FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64
+    #undef __FLT128_HAS_QUIET_NAN__
+    #define __FLT128_HAS_QUIET_NAN__ 1
+    #undef __INTMAX_MAX__
+    #define __INTMAX_MAX__ 0x7fffffffffffffffLL
+    #undef __INT_FAST8_TYPE__
+    #define __INT_FAST8_TYPE__ signed char
+    #undef __FLT64X_MIN__
+    #define __FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x
+    #undef __GNUC_STDC_INLINE__
+    #define __GNUC_STDC_INLINE__ 1
+    #undef __FLT64_HAS_DENORM__
+    #define __FLT64_HAS_DENORM__ 1
+    #undef __FLT32_EPSILON__
+    #define __FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32
+    #undef __FLT16_HAS_DENORM__
+    #define __FLT16_HAS_DENORM__ 1
+    #undef __DBL_DECIMAL_DIG__
+    #define __DBL_DECIMAL_DIG__ 17
+    #undef __INT_FAST8_WIDTH__
+    #define __INT_FAST8_WIDTH__ 8
+    #undef __FXSR__
+    #define __FXSR__ 1
+    #undef __FLT32X_MAX__
+    #define __FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x
+    #undef __DBL_NORM_MAX__
+    #define __DBL_NORM_MAX__ ((double)1.79769313486231570814527423731704357e+308L)
+    #undef __BYTE_ORDER__
+    #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+    #undef __GCC_DESTRUCTIVE_SIZE
+    #define __GCC_DESTRUCTIVE_SIZE 64
+    #undef __INTMAX_WIDTH__
+    #define __INTMAX_WIDTH__ 64
+    #undef __ORDER_BIG_ENDIAN__
+    #define __ORDER_BIG_ENDIAN__ 4321
+    #undef __FLT32_DIG__
+    #define __FLT32_DIG__ 6
+    #undef __UINT32_C
+    #define __UINT32_C(c) c ## U
+    #undef __FLT_DENORM_MIN__
+    #define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F
+    #undef __INT8_MAX__
+    #define __INT8_MAX__ 0x7f
+    #undef __LONG_WIDTH__
+    #define __LONG_WIDTH__ 32
+    #undef __DBL_MIN__
+    #define __DBL_MIN__ ((double)2.22507385850720138309023271733240406e-308L)
+    #undef __PIC__
+    #define __PIC__ 2
+    #undef __INT32_MAX__
+    #define __INT32_MAX__ 0x7fffffff
+    #undef __UINT_FAST32_TYPE__
+    #define __UINT_FAST32_TYPE__ unsigned int
+    #undef __FLT32X_NORM_MAX__
+    #define __FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x
+    #undef __CHAR32_TYPE__
+    #define __CHAR32_TYPE__ unsigned int
+    #undef __FLT_MAX__
+    #define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F
+    #undef __SSE2__
+    #define __SSE2__ 1
+    #undef __INT32_TYPE__
+    #define __INT32_TYPE__ int
+    #undef __SIZEOF_DOUBLE__
+    #define __SIZEOF_DOUBLE__ 8
+    #undef __FLT_MIN_10_EXP__
+    #define __FLT_MIN_10_EXP__ (-37)
+    #undef __FLT64_MIN__
+    #define __FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64
+    #undef __INT_LEAST32_WIDTH__
+    #define __INT_LEAST32_WIDTH__ 32
+    #undef __INTMAX_TYPE__
+    #define __INTMAX_TYPE__ long long int
+    #undef __FLT32X_HAS_QUIET_NAN__
+    #define __FLT32X_HAS_QUIET_NAN__ 1
+    #undef __ATOMIC_CONSUME
+    #define __ATOMIC_CONSUME 1
+    #undef __GNUC_MINOR__
+    #define __GNUC_MINOR__ 1
+    #undef __UINTMAX_MAX__
+    #define __UINTMAX_MAX__ 0xffffffffffffffffULL
+    #undef __PIE__
+    #define __PIE__ 2
+    #undef __FLT32X_DENORM_MIN__
+    #define __FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x
+    #undef __DBL_MAX_10_EXP__
+    #define __DBL_MAX_10_EXP__ 308
+    #undef __LDBL_DENORM_MIN__
+    #define __LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L
+    #undef __INT16_C
+    #define __INT16_C(c) c
+    #undef __PTRDIFF_TYPE__
+    #define __PTRDIFF_TYPE__ int
+    #undef __FLT32X_MIN_10_EXP__
+    #define __FLT32X_MIN_10_EXP__ (-307)
+    #undef __UINTPTR_TYPE__
+    #define __UINTPTR_TYPE__ unsigned int
+    #undef __DEC64_SUBNORMAL_MIN__
+    #define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
+    #undef __DEC128_MANT_DIG__
+    #define __DEC128_MANT_DIG__ 34
+    #undef __LDBL_MIN_10_EXP__
+    #define __LDBL_MIN_10_EXP__ (-4931)
+    #undef __SIZEOF_LONG_LONG__
+    #define __SIZEOF_LONG_LONG__ 8
+    #undef __FLT128_DECIMAL_DIG__
+    #define __FLT128_DECIMAL_DIG__ 36
+    #undef __GCC_ATOMIC_LLONG_LOCK_FREE
+    #define __GCC_ATOMIC_LLONG_LOCK_FREE 2
+    #undef __FLT32_HAS_QUIET_NAN__
+    #define __FLT32_HAS_QUIET_NAN__ 1
+    #undef __FLT_DECIMAL_DIG__
+    #define __FLT_DECIMAL_DIG__ 9
+    #undef __UINT_FAST16_MAX__
+    #define __UINT_FAST16_MAX__ 0xffffffffU
+    #undef __LDBL_NORM_MAX__
+    #define __LDBL_NORM_MAX__ 1.18973149535723176502126385303097021e+4932L
+    #undef __GCC_ATOMIC_SHORT_LOCK_FREE
+    #define __GCC_ATOMIC_SHORT_LOCK_FREE 2
+    #undef __SIZE_MAX__
+    #define __SIZE_MAX__ 0xffffffffU
+    #undef __UINT_FAST8_TYPE__
+    #define __UINT_FAST8_TYPE__ unsigned char
+    #undef __ATOMIC_ACQ_REL
+    #define __ATOMIC_ACQ_REL 4
+    #undef __ATOMIC_RELEASE
+    #define __ATOMIC_RELEASE 3
+eof: (-1)
+errno:
+    e2big: '7'
+    eacces: '13'
+    eaddrinuse: '98'
+    eaddrnotavail: '99'
+    eafnosupport: '97'
+    eagain: '11'
+    ealready: '114'
+    ebade: '52'
+    ebadf: '9'
+    ebadfd: '77'
+    ebadmsg: '74'
+    ebadr: '53'
+    ebadrqc: '56'
+    ebadslt: '57'
+    ebusy: '16'
+    ecanceled: '125'
+    echild: '10'
+    echrng: '44'
+    ecomm: '70'
+    econnaborted: '103'
+    econnrefused: '111'
+    econnreset: '104'
+    edeadlk: '35'
+    edeadlock: '35'
+    edestaddrreq: '89'
+    edom: '33'
+    edquot: '122'
+    eexist: '17'
+    efault: '14'
+    efbig: '27'
+    ehostdown: '112'
+    ehostunreach: '113'
+    eidrm: '43'
+    eilseq: '84'
+    einprogress: '115'
+    eintr: '4'
+    einval: '22'
+    eio: '5'
+    eisconn: '106'
+    eisdir: '21'
+    eisnam: '120'
+    ekeyexpired: '127'
+    ekeyrejected: '129'
+    ekeyrevoked: '128'
+    el2hlt: '51'
+    el2nsync: '45'
+    el3hlt: '46'
+    el3rst: '47'
+    elibacc: '79'
+    elibbad: '80'
+    elibexec: '83'
+    elibmax: '82'
+    elibscn: '81'
+    eloop: '40'
+    emediumtype: '124'
+    emfile: '24'
+    emlink: '31'
+    emsgsize: '90'
+    emultihop: '72'
+    enametoolong: '36'
+    enetdown: '100'
+    enetreset: '102'
+    enetunreach: '101'
+    enfile: '23'
+    enobufs: '105'
+    enodata: '61'
+    enodev: '19'
+    enoent: '2'
+    enoexec: '8'
+    enokey: '126'
+    enolck: '37'
+    enolink: '67'
+    enomedium: '123'
+    enomem: '12'
+    enomsg: '42'
+    enonet: '64'
+    enopkg: '65'
+    enoprotoopt: '92'
+    enospc: '28'
+    enosr: '63'
+    enostr: '60'
+    enosys: '38'
+    enotblk: '15'
+    enotconn: '107'
+    enotdir: '20'
+    enotempty: '39'
+    enotrecoverable: '131'
+    enotsock: '88'
+    enotsup: '95'
+    enotty: '25'
+    enotuniq: '76'
+    enxio: '6'
+    eopnotsupp: '95'
+    eoverflow: '75'
+    eownerdead: '130'
+    eperm: '1'
+    epfnosupport: '96'
+    epipe: '32'
+    eproto: '71'
+    eprotonosupport: '93'
+    eprototype: '91'
+    erange: '34'
+    eremchg: '78'
+    eremote: '66'
+    eremoteio: '121'
+    erestart: '85'
+    erofs: '30'
+    eshutdown: '108'
+    esocktnosupport: '94'
+    espipe: '29'
+    esrch: '3'
+    estale: '116'
+    estrpipe: '86'
+    etime: '62'
+    etimedout: '110'
+    etxtbsy: '26'
+    euclean: '117'
+    eunatch: '49'
+    eusers: '87'
+    ewouldblock: '11'
+    exdev: '18'
+    exfull: '54'
+filename_max: '4096'
+fopen_max: '16'
+has__builtin_va_list: true
+host_name_max: '64'
+int_fast16_t: int
+int_fast32_t: int
+int_fast64_t: long long
+int_fast8_t: signed char
+intptr_t: int
+l_tmpnam: '20'
+little_endian: true
+machdep_name: machdep_gcc_x86_32
+mb_cur_max: ((size_t) 16 )
+nsig: (64 + 1)
+path_max: '4096'
+posix_version: 200809L
+ptrdiff_t: int
+rand_max: '2147483647'
+sig_atomic_t: int
+size_t: unsigned int
+sizeof_double: 8
+sizeof_float: 4
+sizeof_fun: 1
+sizeof_int: 4
+sizeof_long: 4
+sizeof_longdouble: 12
+sizeof_longlong: 8
+sizeof_ptr: 4
+sizeof_short: 2
+sizeof_void: 1
+ssize_t: int
+time_t: long
+tmp_max: '238328'
+tty_name_max: '32'
+uint_fast16_t: unsigned int
+uint_fast32_t: unsigned int
+uint_fast64_t: unsigned long long
+uint_fast8_t: unsigned char
+uintptr_t: unsigned int
+version: gcc (GCC) 13.1.1 20230429
+wchar_t: long
+weof: (0xffffffffu)
+wint_t: unsigned int
+wordsize: '32'
diff --git a/share/machdeps/machdep_gcc_x86_64.yaml b/share/machdeps/machdep_gcc_x86_64.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6c81caac58ab722684b40814e8d81381839cff2d
--- /dev/null
+++ b/share/machdeps/machdep_gcc_x86_64.yaml
@@ -0,0 +1,965 @@
+alignof_aligned: 16
+alignof_double: 8
+alignof_float: 4
+alignof_fun: 1
+alignof_int: 4
+alignof_long: 8
+alignof_longdouble: 16
+alignof_longlong: 8
+alignof_ptr: 8
+alignof_short: 2
+alignof_str: 1
+bufsiz: '8192'
+char_is_unsigned: false
+compiler: gcc
+cpp_arch_flags:
+- -m64
+custom_defs: |
+    #undef __DBL_MIN_EXP__
+    #define __DBL_MIN_EXP__ (-1021)
+    #undef __UINT_LEAST16_MAX__
+    #define __UINT_LEAST16_MAX__ 0xffff
+    #undef __FLT16_HAS_QUIET_NAN__
+    #define __FLT16_HAS_QUIET_NAN__ 1
+    #undef __ATOMIC_ACQUIRE
+    #define __ATOMIC_ACQUIRE 2
+    #undef __FLT128_MAX_10_EXP__
+    #define __FLT128_MAX_10_EXP__ 4932
+    #undef __FLT_MIN__
+    #define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F
+    #undef __GCC_IEC_559_COMPLEX
+    #define __GCC_IEC_559_COMPLEX 2
+    #undef __UINT_LEAST8_TYPE__
+    #define __UINT_LEAST8_TYPE__ unsigned char
+    #undef __SIZEOF_FLOAT80__
+    #define __SIZEOF_FLOAT80__ 16
+    #undef __BFLT16_DENORM_MIN__
+    #define __BFLT16_DENORM_MIN__ 9.18354961579912115600575419704879436e-41BF16
+    #undef __INTMAX_C
+    #define __INTMAX_C(c) c ## L
+    #undef __CHAR_BIT__
+    #define __CHAR_BIT__ 8
+    #undef __UINT8_MAX__
+    #define __UINT8_MAX__ 0xff
+    #undef __SCHAR_WIDTH__
+    #define __SCHAR_WIDTH__ 8
+    #undef __WINT_MAX__
+    #define __WINT_MAX__ 0xffffffffU
+    #undef __FLT32_MIN_EXP__
+    #define __FLT32_MIN_EXP__ (-125)
+    #undef __BFLT16_NORM_MAX__
+    #define __BFLT16_NORM_MAX__ 3.38953138925153547590470800371487867e+38BF16
+    #undef __BFLT16_MIN_10_EXP__
+    #define __BFLT16_MIN_10_EXP__ (-37)
+    #undef __ORDER_LITTLE_ENDIAN__
+    #define __ORDER_LITTLE_ENDIAN__ 1234
+    #undef __WCHAR_MAX__
+    #define __WCHAR_MAX__ 0x7fffffff
+    #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
+    #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
+    #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
+    #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
+    #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
+    #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
+    #undef __GCC_ATOMIC_CHAR_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR_LOCK_FREE 2
+    #undef __GCC_IEC_559
+    #define __GCC_IEC_559 2
+    #undef __FLT32X_DECIMAL_DIG__
+    #define __FLT32X_DECIMAL_DIG__ 17
+    #undef __FLT_EVAL_METHOD__
+    #define __FLT_EVAL_METHOD__ 0
+    #undef __FLT64_DECIMAL_DIG__
+    #define __FLT64_DECIMAL_DIG__ 17
+    #undef __GCC_ATOMIC_CHAR32_T_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
+    #undef __UINT_FAST64_MAX__
+    #define __UINT_FAST64_MAX__ 0xffffffffffffffffUL
+    #undef __SIG_ATOMIC_TYPE__
+    #define __SIG_ATOMIC_TYPE__ int
+    #undef __DBL_MIN_10_EXP__
+    #define __DBL_MIN_10_EXP__ (-307)
+    #undef __FINITE_MATH_ONLY__
+    #define __FINITE_MATH_ONLY__ 0
+    #undef __FLT32X_MAX_EXP__
+    #define __FLT32X_MAX_EXP__ 1024
+    #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
+    #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+    #undef __FLT32_HAS_DENORM__
+    #define __FLT32_HAS_DENORM__ 1
+    #undef __UINT_FAST8_MAX__
+    #define __UINT_FAST8_MAX__ 0xff
+    #undef __FLT32_MAX_10_EXP__
+    #define __FLT32_MAX_10_EXP__ 38
+    #undef __DEC64_MAX_EXP__
+    #define __DEC64_MAX_EXP__ 385
+    #undef __INT8_C
+    #define __INT8_C(c) c
+    #undef __INT_LEAST8_WIDTH__
+    #define __INT_LEAST8_WIDTH__ 8
+    #undef __UINT_LEAST64_MAX__
+    #define __UINT_LEAST64_MAX__ 0xffffffffffffffffUL
+    #undef __SHRT_MAX__
+    #define __SHRT_MAX__ 0x7fff
+    #undef __LDBL_MAX__
+    #define __LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L
+    #undef __FLT64X_MAX_10_EXP__
+    #define __FLT64X_MAX_10_EXP__ 4932
+    #undef __BFLT16_MAX_10_EXP__
+    #define __BFLT16_MAX_10_EXP__ 38
+    #undef __BFLT16_MAX_EXP__
+    #define __BFLT16_MAX_EXP__ 128
+    #undef __LDBL_IS_IEC_60559__
+    #define __LDBL_IS_IEC_60559__ 1
+    #undef __FLT64X_HAS_QUIET_NAN__
+    #define __FLT64X_HAS_QUIET_NAN__ 1
+    #undef __UINT_LEAST8_MAX__
+    #define __UINT_LEAST8_MAX__ 0xff
+    #undef __GCC_ATOMIC_BOOL_LOCK_FREE
+    #define __GCC_ATOMIC_BOOL_LOCK_FREE 2
+    #undef __FLT128_DENORM_MIN__
+    #define __FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128
+    #undef __UINTMAX_TYPE__
+    #define __UINTMAX_TYPE__ long unsigned int
+    #undef __BFLT16_DECIMAL_DIG__
+    #define __BFLT16_DECIMAL_DIG__ 4
+    #undef __linux
+    #define __linux 1
+    #undef __DEC32_EPSILON__
+    #define __DEC32_EPSILON__ 1E-6DF
+    #undef __FLT_EVAL_METHOD_TS_18661_3__
+    #define __FLT_EVAL_METHOD_TS_18661_3__ 0
+    #undef __UINT32_MAX__
+    #define __UINT32_MAX__ 0xffffffffU
+    #undef __DBL_DENORM_MIN__
+    #define __DBL_DENORM_MIN__ ((double)4.94065645841246544176568792868221372e-324L)
+    #undef __FLT128_MIN_EXP__
+    #define __FLT128_MIN_EXP__ (-16381)
+    #undef __WINT_MIN__
+    #define __WINT_MIN__ 0U
+    #undef __FLT128_MIN_10_EXP__
+    #define __FLT128_MIN_10_EXP__ (-4931)
+    #undef __FLT32X_IS_IEC_60559__
+    #define __FLT32X_IS_IEC_60559__ 1
+    #undef __INT_LEAST16_WIDTH__
+    #define __INT_LEAST16_WIDTH__ 16
+    #undef __SCHAR_MAX__
+    #define __SCHAR_MAX__ 0x7f
+    #undef __FLT128_MANT_DIG__
+    #define __FLT128_MANT_DIG__ 113
+    #undef __WCHAR_MIN__
+    #define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
+    #undef __INT64_C
+    #define __INT64_C(c) c ## L
+    #undef __SSP_STRONG__
+    #define __SSP_STRONG__ 3
+    #undef __GCC_ATOMIC_POINTER_LOCK_FREE
+    #define __GCC_ATOMIC_POINTER_LOCK_FREE 2
+    #undef __ATOMIC_SEQ_CST
+    #define __ATOMIC_SEQ_CST 5
+    #undef __unix
+    #define __unix 1
+    #undef __INT_LEAST64_MAX__
+    #define __INT_LEAST64_MAX__ 0x7fffffffffffffffL
+    #undef __FLT32X_MANT_DIG__
+    #define __FLT32X_MANT_DIG__ 53
+    #undef __FLT64X_EPSILON__
+    #define __FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x
+    #undef __DEC64_MIN_EXP__
+    #define __DEC64_MIN_EXP__ (-382)
+    #undef __DBL_DIG__
+    #define __DBL_DIG__ 15
+    #undef __FLT_EPSILON__
+    #define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F
+    #undef __SHRT_WIDTH__
+    #define __SHRT_WIDTH__ 16
+    #undef __FLT32_IS_IEC_60559__
+    #define __FLT32_IS_IEC_60559__ 1
+    #undef __LDBL_MIN__
+    #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
+    #undef __DBL_IS_IEC_60559__
+    #define __DBL_IS_IEC_60559__ 1
+    #undef __DEC32_MAX__
+    #define __DEC32_MAX__ 9.999999E96DF
+    #undef __FLT64X_DENORM_MIN__
+    #define __FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x
+    #undef __FLT32X_HAS_INFINITY__
+    #define __FLT32X_HAS_INFINITY__ 1
+    #undef __unix__
+    #define __unix__ 1
+    #undef __INT_WIDTH__
+    #define __INT_WIDTH__ 32
+    #undef __DECIMAL_DIG__
+    #define __DECIMAL_DIG__ 21
+    #undef __FLT64_EPSILON__
+    #define __FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64
+    #undef __gnu_linux__
+    #define __gnu_linux__ 1
+    #undef __FLT128_IS_IEC_60559__
+    #define __FLT128_IS_IEC_60559__ 1
+    #undef __FLT64X_MIN_10_EXP__
+    #define __FLT64X_MIN_10_EXP__ (-4931)
+    #undef __LDBL_HAS_QUIET_NAN__
+    #define __LDBL_HAS_QUIET_NAN__ 1
+    #undef __FLT16_MIN_EXP__
+    #define __FLT16_MIN_EXP__ (-13)
+    #undef __FLT64_MANT_DIG__
+    #define __FLT64_MANT_DIG__ 53
+    #undef __FLT64X_MANT_DIG__
+    #define __FLT64X_MANT_DIG__ 64
+    #undef __BFLT16_DIG__
+    #define __BFLT16_DIG__ 2
+    #undef __GNUC__
+    #define __GNUC__ 13
+    #undef __pie__
+    #define __pie__ 2
+    #undef __MMX__
+    #define __MMX__ 1
+    #undef __FLT_HAS_DENORM__
+    #define __FLT_HAS_DENORM__ 1
+    #undef __SIZEOF_LONG_DOUBLE__
+    #define __SIZEOF_LONG_DOUBLE__ 16
+    #undef __BIGGEST_ALIGNMENT__
+    #define __BIGGEST_ALIGNMENT__ 16
+    #undef __FLT64_MAX_10_EXP__
+    #define __FLT64_MAX_10_EXP__ 308
+    #undef __BFLT16_IS_IEC_60559__
+    #define __BFLT16_IS_IEC_60559__ 0
+    #undef __FLT16_MAX_10_EXP__
+    #define __FLT16_MAX_10_EXP__ 4
+    #undef __DBL_MAX__
+    #define __DBL_MAX__ ((double)1.79769313486231570814527423731704357e+308L)
+    #undef __INT_FAST32_MAX__
+    #define __INT_FAST32_MAX__ 0x7fffffffffffffffL
+    #undef __DBL_HAS_INFINITY__
+    #define __DBL_HAS_INFINITY__ 1
+    #undef __INT64_MAX__
+    #define __INT64_MAX__ 0x7fffffffffffffffL
+    #undef __SIZEOF_FLOAT__
+    #define __SIZEOF_FLOAT__ 4
+    #undef __HAVE_SPECULATION_SAFE_VALUE
+    #define __HAVE_SPECULATION_SAFE_VALUE 1
+    #undef __DEC32_MIN_EXP__
+    #define __DEC32_MIN_EXP__ (-94)
+    #undef __INTPTR_WIDTH__
+    #define __INTPTR_WIDTH__ 64
+    #undef __UINT_LEAST32_MAX__
+    #define __UINT_LEAST32_MAX__ 0xffffffffU
+    #undef __FLT32X_HAS_DENORM__
+    #define __FLT32X_HAS_DENORM__ 1
+    #undef __INT_FAST16_TYPE__
+    #define __INT_FAST16_TYPE__ long int
+    #undef __MMX_WITH_SSE__
+    #define __MMX_WITH_SSE__ 1
+    #undef __LDBL_HAS_DENORM__
+    #define __LDBL_HAS_DENORM__ 1
+    #undef __SEG_GS
+    #define __SEG_GS 1
+    #undef __BFLT16_EPSILON__
+    #define __BFLT16_EPSILON__ 7.81250000000000000000000000000000000e-3BF16
+    #undef __FLT128_HAS_INFINITY__
+    #define __FLT128_HAS_INFINITY__ 1
+    #undef __DEC32_MIN__
+    #define __DEC32_MIN__ 1E-95DF
+    #undef __DBL_MAX_EXP__
+    #define __DBL_MAX_EXP__ 1024
+    #undef __WCHAR_WIDTH__
+    #define __WCHAR_WIDTH__ 32
+    #undef __FLT32_MAX__
+    #define __FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32
+    #undef __DEC128_EPSILON__
+    #define __DEC128_EPSILON__ 1E-33DL
+    #undef __FLT16_DECIMAL_DIG__
+    #define __FLT16_DECIMAL_DIG__ 5
+    #undef __SSE2_MATH__
+    #define __SSE2_MATH__ 1
+    #undef __ATOMIC_HLE_RELEASE
+    #define __ATOMIC_HLE_RELEASE 131072
+    #undef __PTRDIFF_MAX__
+    #define __PTRDIFF_MAX__ 0x7fffffffffffffffL
+    #undef __amd64
+    #define __amd64 1
+    #undef __ATOMIC_HLE_ACQUIRE
+    #define __ATOMIC_HLE_ACQUIRE 65536
+    #undef __LONG_LONG_MAX__
+    #define __LONG_LONG_MAX__ 0x7fffffffffffffffLL
+    #undef __SIZEOF_SIZE_T__
+    #define __SIZEOF_SIZE_T__ 8
+    #undef __BFLT16_HAS_INFINITY__
+    #define __BFLT16_HAS_INFINITY__ 1
+    #undef __FLT64X_MIN_EXP__
+    #define __FLT64X_MIN_EXP__ (-16381)
+    #undef __SIZEOF_WINT_T__
+    #define __SIZEOF_WINT_T__ 4
+    #undef __LONG_LONG_WIDTH__
+    #define __LONG_LONG_WIDTH__ 64
+    #undef __FLT32_MAX_EXP__
+    #define __FLT32_MAX_EXP__ 128
+    #undef __GXX_ABI_VERSION
+    #define __GXX_ABI_VERSION 1018
+    #undef __FLT_MIN_EXP__
+    #define __FLT_MIN_EXP__ (-125)
+    #undef __GCC_HAVE_DWARF2_CFI_ASM
+    #define __GCC_HAVE_DWARF2_CFI_ASM 1
+    #undef __INT16_MAX__
+    #define __INT16_MAX__ 0x7fff
+    #undef __x86_64
+    #define __x86_64 1
+    #undef __INT_FAST64_TYPE__
+    #define __INT_FAST64_TYPE__ long int
+    #undef __BFLT16_MAX__
+    #define __BFLT16_MAX__ 3.38953138925153547590470800371487867e+38BF16
+    #undef __BFLT16_HAS_DENORM__
+    #define __BFLT16_HAS_DENORM__ 1
+    #undef __FLT64_DENORM_MIN__
+    #define __FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64
+    #undef __FLT16_DENORM_MIN__
+    #define __FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16
+    #undef __FLT128_EPSILON__
+    #define __FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128
+    #undef __FLT64X_NORM_MAX__
+    #define __FLT64X_NORM_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+    #undef __SIZEOF_POINTER__
+    #define __SIZEOF_POINTER__ 8
+    #undef __SIZE_TYPE__
+    #define __SIZE_TYPE__ long unsigned int
+    #undef __LP64__
+    #define __LP64__ 1
+    #undef __DBL_HAS_QUIET_NAN__
+    #define __DBL_HAS_QUIET_NAN__ 1
+    #undef __FLT32X_EPSILON__
+    #define __FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x
+    #undef __LDBL_MAX_EXP__
+    #define __LDBL_MAX_EXP__ 16384
+    #undef __DECIMAL_BID_FORMAT__
+    #define __DECIMAL_BID_FORMAT__ 1
+    #undef __FLT64_MIN_EXP__
+    #define __FLT64_MIN_EXP__ (-1021)
+    #undef __FLT64_MIN_10_EXP__
+    #define __FLT64_MIN_10_EXP__ (-307)
+    #undef __FLT16_MIN_10_EXP__
+    #define __FLT16_MIN_10_EXP__ (-4)
+    #undef __FLT64X_DECIMAL_DIG__
+    #define __FLT64X_DECIMAL_DIG__ 21
+    #undef __DEC128_MIN__
+    #define __DEC128_MIN__ 1E-6143DL
+    #undef __REGISTER_PREFIX__
+    #define __REGISTER_PREFIX__
+    #undef __UINT16_MAX__
+    #define __UINT16_MAX__ 0xffff
+    #undef __DBL_HAS_DENORM__
+    #define __DBL_HAS_DENORM__ 1
+    #undef __FLT32_MIN__
+    #define __FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32
+    #undef __UINT8_TYPE__
+    #define __UINT8_TYPE__ unsigned char
+    #undef __FLT_DIG__
+    #define __FLT_DIG__ 6
+    #undef __NO_INLINE__
+    #define __NO_INLINE__ 1
+    #undef __DEC_EVAL_METHOD__
+    #define __DEC_EVAL_METHOD__ 2
+    #undef __FLT_MANT_DIG__
+    #define __FLT_MANT_DIG__ 24
+    #undef __LDBL_DECIMAL_DIG__
+    #define __LDBL_DECIMAL_DIG__ 21
+    #undef __VERSION__
+    #define __VERSION__ "13.1.1 20230429"
+    #undef __UINT64_C
+    #define __UINT64_C(c) c ## UL
+    #undef _STDC_PREDEF_H
+    #define _STDC_PREDEF_H 1
+    #undef __INT_LEAST32_MAX__
+    #define __INT_LEAST32_MAX__ 0x7fffffff
+    #undef __GCC_ATOMIC_INT_LOCK_FREE
+    #define __GCC_ATOMIC_INT_LOCK_FREE 2
+    #undef __FLT128_MAX_EXP__
+    #define __FLT128_MAX_EXP__ 16384
+    #undef __FLT32_MANT_DIG__
+    #define __FLT32_MANT_DIG__ 24
+    #undef __FLOAT_WORD_ORDER__
+    #define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
+    #undef __FLT32X_MIN_EXP__
+    #define __FLT32X_MIN_EXP__ (-1021)
+    #undef __BFLT16_MIN__
+    #define __BFLT16_MIN__ 1.17549435082228750796873653722224568e-38BF16
+    #undef __FLT128_HAS_DENORM__
+    #define __FLT128_HAS_DENORM__ 1
+    #undef __FLT32_DECIMAL_DIG__
+    #define __FLT32_DECIMAL_DIG__ 9
+    #undef __FLT128_DIG__
+    #define __FLT128_DIG__ 33
+    #undef __INT32_C
+    #define __INT32_C(c) c
+    #undef __DEC64_EPSILON__
+    #define __DEC64_EPSILON__ 1E-15DD
+    #undef __ORDER_PDP_ENDIAN__
+    #define __ORDER_PDP_ENDIAN__ 3412
+    #undef __DEC128_MIN_EXP__
+    #define __DEC128_MIN_EXP__ (-6142)
+    #undef __DEC128_MAX__
+    #define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
+    #undef __INT_FAST32_TYPE__
+    #define __INT_FAST32_TYPE__ long int
+    #undef __UINT_LEAST16_TYPE__
+    #define __UINT_LEAST16_TYPE__ short unsigned int
+    #undef __DEC128_MAX_EXP__
+    #define __DEC128_MAX_EXP__ 6145
+    #undef unix
+    #define unix 1
+    #undef __UINT64_MAX__
+    #define __UINT64_MAX__ 0xffffffffffffffffUL
+    #undef __FLT_IS_IEC_60559__
+    #define __FLT_IS_IEC_60559__ 1
+    #undef __GNUC_WIDE_EXECUTION_CHARSET_NAME
+    #define __GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE"
+    #undef __FLT64X_DIG__
+    #define __FLT64X_DIG__ 18
+    #undef __INT8_TYPE__
+    #define __INT8_TYPE__ signed char
+    #undef __ELF__
+    #define __ELF__ 1
+    #undef __GCC_ASM_FLAG_OUTPUTS__
+    #define __GCC_ASM_FLAG_OUTPUTS__ 1
+    #undef __UINT32_TYPE__
+    #define __UINT32_TYPE__ unsigned int
+    #undef __BFLT16_HAS_QUIET_NAN__
+    #define __BFLT16_HAS_QUIET_NAN__ 1
+    #undef __FLT_RADIX__
+    #define __FLT_RADIX__ 2
+    #undef __INT_LEAST16_TYPE__
+    #define __INT_LEAST16_TYPE__ short int
+    #undef __LDBL_EPSILON__
+    #define __LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L
+    #undef __UINTMAX_C
+    #define __UINTMAX_C(c) c ## UL
+    #undef __FLT16_DIG__
+    #define __FLT16_DIG__ 3
+    #undef __SSE_MATH__
+    #define __SSE_MATH__ 1
+    #undef __k8
+    #define __k8 1
+    #undef __FLT32X_MIN__
+    #define __FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x
+    #undef __SIG_ATOMIC_MAX__
+    #define __SIG_ATOMIC_MAX__ 0x7fffffff
+    #undef __GCC_ATOMIC_WCHAR_T_LOCK_FREE
+    #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
+    #undef __USER_LABEL_PREFIX__
+    #define __USER_LABEL_PREFIX__
+    #undef __SIZEOF_PTRDIFF_T__
+    #define __SIZEOF_PTRDIFF_T__ 8
+    #undef __FLT64X_HAS_INFINITY__
+    #define __FLT64X_HAS_INFINITY__ 1
+    #undef __FLT32_HAS_INFINITY__
+    #define __FLT32_HAS_INFINITY__ 1
+    #undef __SIZEOF_LONG__
+    #define __SIZEOF_LONG__ 8
+    #undef __LDBL_DIG__
+    #define __LDBL_DIG__ 18
+    #undef __FLT64_IS_IEC_60559__
+    #define __FLT64_IS_IEC_60559__ 1
+    #undef __x86_64__
+    #define __x86_64__ 1
+    #undef __FLT16_IS_IEC_60559__
+    #define __FLT16_IS_IEC_60559__ 1
+    #undef __FLT16_MAX_EXP__
+    #define __FLT16_MAX_EXP__ 16
+    #undef __DEC32_SUBNORMAL_MIN__
+    #define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
+    #undef __INT_FAST16_MAX__
+    #define __INT_FAST16_MAX__ 0x7fffffffffffffffL
+    #undef __GCC_CONSTRUCTIVE_SIZE
+    #define __GCC_CONSTRUCTIVE_SIZE 64
+    #undef __FLT64_DIG__
+    #define __FLT64_DIG__ 15
+    #undef __UINT_FAST32_MAX__
+    #define __UINT_FAST32_MAX__ 0xffffffffffffffffUL
+    #undef __UINT_LEAST64_TYPE__
+    #define __UINT_LEAST64_TYPE__ long unsigned int
+    #undef __FLT16_EPSILON__
+    #define __FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16
+    #undef __FLT_HAS_QUIET_NAN__
+    #define __FLT_HAS_QUIET_NAN__ 1
+    #undef __FLT_MAX_10_EXP__
+    #define __FLT_MAX_10_EXP__ 38
+    #undef __LONG_MAX__
+    #define __LONG_MAX__ 0x7fffffffffffffffL
+    #undef __FLT64X_HAS_DENORM__
+    #define __FLT64X_HAS_DENORM__ 1
+    #undef __DEC128_SUBNORMAL_MIN__
+    #define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
+    #undef __FLT_HAS_INFINITY__
+    #define __FLT_HAS_INFINITY__ 1
+    #undef __GNUC_EXECUTION_CHARSET_NAME
+    #define __GNUC_EXECUTION_CHARSET_NAME "UTF-8"
+    #undef __UINT_FAST16_TYPE__
+    #define __UINT_FAST16_TYPE__ long unsigned int
+    #undef __DEC64_MAX__
+    #define __DEC64_MAX__ 9.999999999999999E384DD
+    #undef __INT_FAST32_WIDTH__
+    #define __INT_FAST32_WIDTH__ 64
+    #undef __CHAR16_TYPE__
+    #define __CHAR16_TYPE__ short unsigned int
+    #undef __PRAGMA_REDEFINE_EXTNAME
+    #define __PRAGMA_REDEFINE_EXTNAME 1
+    #undef __SIZE_WIDTH__
+    #define __SIZE_WIDTH__ 64
+    #undef __SEG_FS
+    #define __SEG_FS 1
+    #undef __INT_LEAST16_MAX__
+    #define __INT_LEAST16_MAX__ 0x7fff
+    #undef __FLT16_NORM_MAX__
+    #define __FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16
+    #undef __DEC64_MANT_DIG__
+    #define __DEC64_MANT_DIG__ 16
+    #undef __FLT32_DENORM_MIN__
+    #define __FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32
+    #undef __SIG_ATOMIC_WIDTH__
+    #define __SIG_ATOMIC_WIDTH__ 32
+    #undef __INT_LEAST64_TYPE__
+    #define __INT_LEAST64_TYPE__ long int
+    #undef __INT16_TYPE__
+    #define __INT16_TYPE__ short int
+    #undef __INT_LEAST8_TYPE__
+    #define __INT_LEAST8_TYPE__ signed char
+    #undef __FLT16_MAX__
+    #define __FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16
+    #undef __FLT128_MIN__
+    #define __FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128
+    #undef __SIZEOF_INT__
+    #define __SIZEOF_INT__ 4
+    #undef __DEC32_MAX_EXP__
+    #define __DEC32_MAX_EXP__ 97
+    #undef __INT_FAST8_MAX__
+    #define __INT_FAST8_MAX__ 0x7f
+    #undef __FLT128_MAX__
+    #define __FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128
+    #undef __INTPTR_MAX__
+    #define __INTPTR_MAX__ 0x7fffffffffffffffL
+    #undef linux
+    #define linux 1
+    #undef __FLT64_HAS_QUIET_NAN__
+    #define __FLT64_HAS_QUIET_NAN__ 1
+    #undef __FLT32_MIN_10_EXP__
+    #define __FLT32_MIN_10_EXP__ (-37)
+    #undef __FLT32X_DIG__
+    #define __FLT32X_DIG__ 15
+    #undef __UINT16_C
+    #define __UINT16_C(c) c
+    #undef __PTRDIFF_WIDTH__
+    #define __PTRDIFF_WIDTH__ 64
+    #undef __LDBL_MANT_DIG__
+    #define __LDBL_MANT_DIG__ 64
+    #undef __INT_FAST16_WIDTH__
+    #define __INT_FAST16_WIDTH__ 64
+    #undef __FLT64_HAS_INFINITY__
+    #define __FLT64_HAS_INFINITY__ 1
+    #undef __FLT64X_MAX__
+    #define __FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+    #undef __FLT16_HAS_INFINITY__
+    #define __FLT16_HAS_INFINITY__ 1
+    #undef __SIG_ATOMIC_MIN__
+    #define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
+    #undef __code_model_small__
+    #define __code_model_small__ 1
+    #undef __GCC_ATOMIC_LONG_LOCK_FREE
+    #define __GCC_ATOMIC_LONG_LOCK_FREE 2
+    #undef __DEC32_MANT_DIG__
+    #define __DEC32_MANT_DIG__ 7
+    #undef __FLT16_MANT_DIG__
+    #define __FLT16_MANT_DIG__ 11
+    #undef __k8__
+    #define __k8__ 1
+    #undef __INTPTR_TYPE__
+    #define __INTPTR_TYPE__ long int
+    #undef __UINT16_TYPE__
+    #define __UINT16_TYPE__ short unsigned int
+    #undef __WCHAR_TYPE__
+    #define __WCHAR_TYPE__ int
+    #undef __pic__
+    #define __pic__ 2
+    #undef __UINTPTR_MAX__
+    #define __UINTPTR_MAX__ 0xffffffffffffffffUL
+    #undef __INT_FAST64_WIDTH__
+    #define __INT_FAST64_WIDTH__ 64
+    #undef __LDBL_HAS_INFINITY__
+    #define __LDBL_HAS_INFINITY__ 1
+    #undef __INT_FAST64_MAX__
+    #define __INT_FAST64_MAX__ 0x7fffffffffffffffL
+    #undef __GCC_ATOMIC_TEST_AND_SET_TRUEVAL
+    #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
+    #undef __FLT_NORM_MAX__
+    #define __FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F
+    #undef __FLT64X_MAX_EXP__
+    #define __FLT64X_MAX_EXP__ 16384
+    #undef __UINT_FAST64_TYPE__
+    #define __UINT_FAST64_TYPE__ long unsigned int
+    #undef __BFLT16_MIN_EXP__
+    #define __BFLT16_MIN_EXP__ (-125)
+    #undef __INT_MAX__
+    #define __INT_MAX__ 0x7fffffff
+    #undef __linux__
+    #define __linux__ 1
+    #undef __INT64_TYPE__
+    #define __INT64_TYPE__ long int
+    #undef __FLT_MAX_EXP__
+    #define __FLT_MAX_EXP__ 128
+    #undef __ORDER_BIG_ENDIAN__
+    #define __ORDER_BIG_ENDIAN__ 4321
+    #undef __DBL_MANT_DIG__
+    #define __DBL_MANT_DIG__ 53
+    #undef __SIZEOF_FLOAT128__
+    #define __SIZEOF_FLOAT128__ 16
+    #undef __BFLT16_MANT_DIG__
+    #define __BFLT16_MANT_DIG__ 8
+    #undef __GCC_ATOMIC_CHAR16_T_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
+    #undef __DEC64_MIN__
+    #define __DEC64_MIN__ 1E-383DD
+    #undef __WINT_TYPE__
+    #define __WINT_TYPE__ unsigned int
+    #undef __UINT_LEAST32_TYPE__
+    #define __UINT_LEAST32_TYPE__ unsigned int
+    #undef __SIZEOF_SHORT__
+    #define __SIZEOF_SHORT__ 2
+    #undef __FLT32_NORM_MAX__
+    #define __FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32
+    #undef __SSE__
+    #define __SSE__ 1
+    #undef __LDBL_MIN_EXP__
+    #define __LDBL_MIN_EXP__ (-16381)
+    #undef __FLT64_MAX__
+    #define __FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64
+    #undef __amd64__
+    #define __amd64__ 1
+    #undef __WINT_WIDTH__
+    #define __WINT_WIDTH__ 32
+    #undef __INT_LEAST8_MAX__
+    #define __INT_LEAST8_MAX__ 0x7f
+    #undef __INT_LEAST64_WIDTH__
+    #define __INT_LEAST64_WIDTH__ 64
+    #undef __FLT32X_MAX_10_EXP__
+    #define __FLT32X_MAX_10_EXP__ 308
+    #undef __SIZEOF_INT128__
+    #define __SIZEOF_INT128__ 16
+    #undef __FLT16_MIN__
+    #define __FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16
+    #undef __FLT64X_IS_IEC_60559__
+    #define __FLT64X_IS_IEC_60559__ 1
+    #undef __LDBL_MAX_10_EXP__
+    #define __LDBL_MAX_10_EXP__ 4932
+    #undef __ATOMIC_RELAXED
+    #define __ATOMIC_RELAXED 0
+    #undef __DBL_EPSILON__
+    #define __DBL_EPSILON__ ((double)2.22044604925031308084726333618164062e-16L)
+    #undef __INT_LEAST32_TYPE__
+    #define __INT_LEAST32_TYPE__ int
+    #undef _LP64
+    #define _LP64 1
+    #undef __UINT8_C
+    #define __UINT8_C(c) c
+    #undef __FLT64_MAX_EXP__
+    #define __FLT64_MAX_EXP__ 1024
+    #undef __SIZEOF_WCHAR_T__
+    #define __SIZEOF_WCHAR_T__ 4
+    #undef __UINT64_TYPE__
+    #define __UINT64_TYPE__ long unsigned int
+    #undef __GNUC_PATCHLEVEL__
+    #define __GNUC_PATCHLEVEL__ 1
+    #undef __FLT128_NORM_MAX__
+    #define __FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128
+    #undef __FLT64_NORM_MAX__
+    #define __FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64
+    #undef __FLT128_HAS_QUIET_NAN__
+    #define __FLT128_HAS_QUIET_NAN__ 1
+    #undef __INTMAX_MAX__
+    #define __INTMAX_MAX__ 0x7fffffffffffffffL
+    #undef __INT_FAST8_TYPE__
+    #define __INT_FAST8_TYPE__ signed char
+    #undef __FLT64X_MIN__
+    #define __FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x
+    #undef __GNUC_STDC_INLINE__
+    #define __GNUC_STDC_INLINE__ 1
+    #undef __FLT64_HAS_DENORM__
+    #define __FLT64_HAS_DENORM__ 1
+    #undef __FLT32_EPSILON__
+    #define __FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32
+    #undef __FLT16_HAS_DENORM__
+    #define __FLT16_HAS_DENORM__ 1
+    #undef __DBL_DECIMAL_DIG__
+    #define __DBL_DECIMAL_DIG__ 17
+    #undef __INT_FAST8_WIDTH__
+    #define __INT_FAST8_WIDTH__ 8
+    #undef __FXSR__
+    #define __FXSR__ 1
+    #undef __FLT32X_MAX__
+    #define __FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x
+    #undef __DBL_NORM_MAX__
+    #define __DBL_NORM_MAX__ ((double)1.79769313486231570814527423731704357e+308L)
+    #undef __BYTE_ORDER__
+    #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+    #undef __GCC_DESTRUCTIVE_SIZE
+    #define __GCC_DESTRUCTIVE_SIZE 64
+    #undef __INTMAX_WIDTH__
+    #define __INTMAX_WIDTH__ 64
+    #undef __FLT32_DIG__
+    #define __FLT32_DIG__ 6
+    #undef __UINT32_C
+    #define __UINT32_C(c) c ## U
+    #undef __FLT_DENORM_MIN__
+    #define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F
+    #undef __INT8_MAX__
+    #define __INT8_MAX__ 0x7f
+    #undef __LONG_WIDTH__
+    #define __LONG_WIDTH__ 64
+    #undef __DBL_MIN__
+    #define __DBL_MIN__ ((double)2.22507385850720138309023271733240406e-308L)
+    #undef __PIC__
+    #define __PIC__ 2
+    #undef __INT32_MAX__
+    #define __INT32_MAX__ 0x7fffffff
+    #undef __UINT_FAST32_TYPE__
+    #define __UINT_FAST32_TYPE__ long unsigned int
+    #undef __FLT32X_NORM_MAX__
+    #define __FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x
+    #undef __CHAR32_TYPE__
+    #define __CHAR32_TYPE__ unsigned int
+    #undef __FLT_MAX__
+    #define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F
+    #undef __SSE2__
+    #define __SSE2__ 1
+    #undef __INT32_TYPE__
+    #define __INT32_TYPE__ int
+    #undef __SIZEOF_DOUBLE__
+    #define __SIZEOF_DOUBLE__ 8
+    #undef __FLT_MIN_10_EXP__
+    #define __FLT_MIN_10_EXP__ (-37)
+    #undef __FLT64_MIN__
+    #define __FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64
+    #undef __INT_LEAST32_WIDTH__
+    #define __INT_LEAST32_WIDTH__ 32
+    #undef __INTMAX_TYPE__
+    #define __INTMAX_TYPE__ long int
+    #undef __FLT32X_HAS_QUIET_NAN__
+    #define __FLT32X_HAS_QUIET_NAN__ 1
+    #undef __ATOMIC_CONSUME
+    #define __ATOMIC_CONSUME 1
+    #undef __GNUC_MINOR__
+    #define __GNUC_MINOR__ 1
+    #undef __UINTMAX_MAX__
+    #define __UINTMAX_MAX__ 0xffffffffffffffffUL
+    #undef __PIE__
+    #define __PIE__ 2
+    #undef __FLT32X_DENORM_MIN__
+    #define __FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x
+    #undef __DBL_MAX_10_EXP__
+    #define __DBL_MAX_10_EXP__ 308
+    #undef __LDBL_DENORM_MIN__
+    #define __LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L
+    #undef __INT16_C
+    #define __INT16_C(c) c
+    #undef __PTRDIFF_TYPE__
+    #define __PTRDIFF_TYPE__ long int
+    #undef __FLT32X_MIN_10_EXP__
+    #define __FLT32X_MIN_10_EXP__ (-307)
+    #undef __UINTPTR_TYPE__
+    #define __UINTPTR_TYPE__ long unsigned int
+    #undef __DEC64_SUBNORMAL_MIN__
+    #define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
+    #undef __DEC128_MANT_DIG__
+    #define __DEC128_MANT_DIG__ 34
+    #undef __LDBL_MIN_10_EXP__
+    #define __LDBL_MIN_10_EXP__ (-4931)
+    #undef __SIZEOF_LONG_LONG__
+    #define __SIZEOF_LONG_LONG__ 8
+    #undef __FLT128_DECIMAL_DIG__
+    #define __FLT128_DECIMAL_DIG__ 36
+    #undef __GCC_ATOMIC_LLONG_LOCK_FREE
+    #define __GCC_ATOMIC_LLONG_LOCK_FREE 2
+    #undef __FLT32_HAS_QUIET_NAN__
+    #define __FLT32_HAS_QUIET_NAN__ 1
+    #undef __FLT_DECIMAL_DIG__
+    #define __FLT_DECIMAL_DIG__ 9
+    #undef __UINT_FAST16_MAX__
+    #define __UINT_FAST16_MAX__ 0xffffffffffffffffUL
+    #undef __LDBL_NORM_MAX__
+    #define __LDBL_NORM_MAX__ 1.18973149535723176502126385303097021e+4932L
+    #undef __GCC_ATOMIC_SHORT_LOCK_FREE
+    #define __GCC_ATOMIC_SHORT_LOCK_FREE 2
+    #undef __SIZE_MAX__
+    #define __SIZE_MAX__ 0xffffffffffffffffUL
+    #undef __UINT_FAST8_TYPE__
+    #define __UINT_FAST8_TYPE__ unsigned char
+    #undef __ATOMIC_ACQ_REL
+    #define __ATOMIC_ACQ_REL 4
+    #undef __ATOMIC_RELEASE
+    #define __ATOMIC_RELEASE 3
+eof: (-1)
+errno:
+    e2big: '7'
+    eacces: '13'
+    eaddrinuse: '98'
+    eaddrnotavail: '99'
+    eafnosupport: '97'
+    eagain: '11'
+    ealready: '114'
+    ebade: '52'
+    ebadf: '9'
+    ebadfd: '77'
+    ebadmsg: '74'
+    ebadr: '53'
+    ebadrqc: '56'
+    ebadslt: '57'
+    ebusy: '16'
+    ecanceled: '125'
+    echild: '10'
+    echrng: '44'
+    ecomm: '70'
+    econnaborted: '103'
+    econnrefused: '111'
+    econnreset: '104'
+    edeadlk: '35'
+    edeadlock: '35'
+    edestaddrreq: '89'
+    edom: '33'
+    edquot: '122'
+    eexist: '17'
+    efault: '14'
+    efbig: '27'
+    ehostdown: '112'
+    ehostunreach: '113'
+    eidrm: '43'
+    eilseq: '84'
+    einprogress: '115'
+    eintr: '4'
+    einval: '22'
+    eio: '5'
+    eisconn: '106'
+    eisdir: '21'
+    eisnam: '120'
+    ekeyexpired: '127'
+    ekeyrejected: '129'
+    ekeyrevoked: '128'
+    el2hlt: '51'
+    el2nsync: '45'
+    el3hlt: '46'
+    el3rst: '47'
+    elibacc: '79'
+    elibbad: '80'
+    elibexec: '83'
+    elibmax: '82'
+    elibscn: '81'
+    eloop: '40'
+    emediumtype: '124'
+    emfile: '24'
+    emlink: '31'
+    emsgsize: '90'
+    emultihop: '72'
+    enametoolong: '36'
+    enetdown: '100'
+    enetreset: '102'
+    enetunreach: '101'
+    enfile: '23'
+    enobufs: '105'
+    enodata: '61'
+    enodev: '19'
+    enoent: '2'
+    enoexec: '8'
+    enokey: '126'
+    enolck: '37'
+    enolink: '67'
+    enomedium: '123'
+    enomem: '12'
+    enomsg: '42'
+    enonet: '64'
+    enopkg: '65'
+    enoprotoopt: '92'
+    enospc: '28'
+    enosr: '63'
+    enostr: '60'
+    enosys: '38'
+    enotblk: '15'
+    enotconn: '107'
+    enotdir: '20'
+    enotempty: '39'
+    enotrecoverable: '131'
+    enotsock: '88'
+    enotsup: '95'
+    enotty: '25'
+    enotuniq: '76'
+    enxio: '6'
+    eopnotsupp: '95'
+    eoverflow: '75'
+    eownerdead: '130'
+    eperm: '1'
+    epfnosupport: '96'
+    epipe: '32'
+    eproto: '71'
+    eprotonosupport: '93'
+    eprototype: '91'
+    erange: '34'
+    eremchg: '78'
+    eremote: '66'
+    eremoteio: '121'
+    erestart: '85'
+    erofs: '30'
+    eshutdown: '108'
+    esocktnosupport: '94'
+    espipe: '29'
+    esrch: '3'
+    estale: '116'
+    estrpipe: '86'
+    etime: '62'
+    etimedout: '110'
+    etxtbsy: '26'
+    euclean: '117'
+    eunatch: '49'
+    eusers: '87'
+    ewouldblock: '11'
+    exdev: '18'
+    exfull: '54'
+filename_max: '4096'
+fopen_max: '16'
+has__builtin_va_list: true
+host_name_max: '64'
+int_fast16_t: long
+int_fast32_t: long
+int_fast64_t: long
+int_fast8_t: signed char
+intptr_t: long
+l_tmpnam: '20'
+little_endian: true
+machdep_name: machdep_gcc_x86_64
+mb_cur_max: ((size_t) 16 )
+nsig: (64 + 1)
+path_max: '4096'
+posix_version: 200809L
+ptrdiff_t: long
+rand_max: '2147483647'
+sig_atomic_t: int
+size_t: unsigned long
+sizeof_double: 8
+sizeof_float: 4
+sizeof_fun: 1
+sizeof_int: 4
+sizeof_long: 8
+sizeof_longdouble: 16
+sizeof_longlong: 8
+sizeof_ptr: 8
+sizeof_short: 2
+sizeof_void: 1
+ssize_t: long
+time_t: long
+tmp_max: '238328'
+tty_name_max: '32'
+uint_fast16_t: unsigned long
+uint_fast32_t: unsigned long
+uint_fast64_t: unsigned long
+uint_fast8_t: unsigned char
+uintptr_t: unsigned long
+version: gcc (GCC) 13.1.1 20230429
+wchar_t: int
+weof: (0xffffffffu)
+wint_t: unsigned int
+wordsize: '64'
diff --git a/share/machdeps/machdep_msvc_x86_64.yaml b/share/machdeps/machdep_msvc_x86_64.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..59f2f5d98f1d29548c658c44e8c2403e5dda32a4
--- /dev/null
+++ b/share/machdeps/machdep_msvc_x86_64.yaml
@@ -0,0 +1,175 @@
+alignof_aligned: 1
+alignof_double: 8
+alignof_float: 4
+alignof_fun: -1
+alignof_int: 4
+alignof_long: 4
+alignof_longdouble: 8
+alignof_longlong: 8
+alignof_ptr: 8
+alignof_short: 2
+alignof_str: 1
+char_is_unsigned: false
+compiler: msvc
+cpp_arch_flags:
+- -m64
+custom_defs: |
+  #define _MSC_FULL_VER 160040219
+  #define _MSC_VER 1600
+  #undef __ptr64
+  #define __ptr64
+  #undef __ptr32
+  #define __ptr32
+  #undef __unaligned
+  #define __unaligned
+  #undef __cdecl
+  #define __cdecl
+  #undef __possibly_notnullterminated
+  #define __possibly_notnullterminated
+  #ifndef errno_t
+  # define errno_t int
+  # define _ERRNO_T_DEFINED
+  #endif
+  #ifndef _WIN64
+  # define _WIN64 1
+  #endif
+  #ifndef _AMD64_
+  # define _AMD64_ 1
+  #endif
+  #ifndef _M_AMD64
+  # define _M_AMD64 1
+  #endif
+  #ifndef _M_X64
+  # define _M_X64 1
+  #endif
+
+errno:
+    eperm: '1'
+    enoent: '2'
+    esrch: '3'
+    eintr: '4'
+    eio: '5'
+    enxio: '6'
+    e2big: '7'
+    enoexec: '8'
+    ebadf: '9'
+    echild: '10'
+    eagain: '11'
+    enomem: '12'
+    eacces: '13'
+    efault: '14'
+    ebusy: '16'
+    eexist: '17'
+    exdev: '18'
+    enodev: '19'
+    enotdir: '20'
+    eisdir: '21'
+    einval: '22'
+    enfile: '23'
+    emfile: '24'
+    enotty: '25'
+    etxtbsy: '139'
+    efbig: '27'
+    enospc: '28'
+    espipe: '29'
+    erofs: '30'
+    emlink: '31'
+    epipe: '32'
+    edom: '33'
+    erange: '34'
+    edeadlk: '36'
+    enametoolong: '38'
+    enolck: '39'
+    enosys: '40'
+    enotempty: '41'
+    eloop: '114'
+    ewouldblock: '140'
+    enomsg: '122'
+    eidrm: '111'
+    edeadlock: '36'
+    enostr: '125'
+    enodata: '120'
+    etime: '137'
+    enosr: '124'
+    enolink: '121'
+    eproto: '134'
+    ebadmsg: '104'
+    eoverflow: '132'
+    eilseq: '42'
+    enotsock: '128'
+    edestaddrreq: '109'
+    emsgsize: '115'
+    eprototype: '136'
+    enoprotoopt: '123'
+    eprotonosupport: '135'
+    enotsup: '129'
+    eopnotsupp: '130'
+    eafnosupport: '102'
+    eaddrinuse: '100'
+    eaddrnotavail: '101'
+    enetdown: '116'
+    enetunreach: '118'
+    enetreset: '117'
+    econnaborted: '106'
+    econnreset: '108'
+    enobufs: '119'
+    eisconn: '113'
+    enotconn: '126'
+    etimedout: '138'
+    econnrefused: '107'
+    ehostunreach: '110'
+    ealready: '103'
+    einprogress: '112'
+    ecanceled: '105'
+    eownerdead: '133'
+    enotrecoverable: '127'
+has__builtin_va_list: false
+int_fast8_t: signed char
+int_fast16_t: signed int
+int_fast32_t: signed int
+int_fast64_t: signed long long
+intptr_t: signed long long
+little_endian: true
+nsig: '23'
+ptrdiff_t: long long
+# NB: wasn't defined at all in old __fc_machdep.h
+sig_atomic_t: int
+size_t: unsigned long long
+sizeof_double: 8
+sizeof_float: 4
+sizeof_fun: -1
+sizeof_int: 4
+sizeof_long: 4
+sizeof_longdouble: 8
+sizeof_longlong: 8
+sizeof_ptr: 8
+sizeof_short: 2
+sizeof_void: 0
+ssize_t: long long
+time_t: long long
+uint_fast8_t: unsigned char
+uint_fast16_t: unsigned int
+uint_fast32_t: unsigned int
+uint_fast64_t: unsigned long long
+uintptr_t: unsigned long long
+version: MSVC - X86-64bits mode
+wchar_t: unsigned short
+weof: (0xffffU)
+wint_t: unsigned short
+wordsize: '64'
+posix_version: ''
+# NB: except for l_tmpnam, the corresponding macro are not defined in the old
+# __fc_machdep.h in the MSVC_X86_64 section. The values below have thus been 
+# taken from gnu
+bufsiz: '8192'
+eof: '(-1)'
+fopen_max: '20'
+host_name_max: '255'
+path_max: '256'
+tty_name_max: '32'
+filename_max: '2048'
+l_tmpnam: '20'
+tmp_max: '0xFFFFFFFF'
+rand_max: '32767'
+mb_cur_max: '((size_t)16)'
+machdep_name: machdep_msvc_x86_64
diff --git a/share/machdeps/machdep_ppc_32.yaml b/share/machdeps/machdep_ppc_32.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..58d1be5602866bb9938417137cb94df3ff5ed8f4
--- /dev/null
+++ b/share/machdeps/machdep_ppc_32.yaml
@@ -0,0 +1,1207 @@
+alignof_aligned: 16
+alignof_double: 8
+alignof_float: 4
+alignof_fun: 4
+alignof_int: 4
+alignof_long: 4
+alignof_longdouble: 16
+alignof_longlong: 8
+alignof_ptr: 4
+alignof_short: 2
+alignof_str: 1
+bufsiz: '8192'
+char_is_unsigned: true
+compiler: clang
+cpp_arch_flags:
+- -target
+- powerpc-apple-linux
+- -mcpu=603
+custom_defs: |
+    #undef _ARCH_603
+    #define _ARCH_603 1
+    #undef _ARCH_PPC
+    #define _ARCH_PPC 1
+    #undef _ARCH_PPCGR
+    #define _ARCH_PPCGR 1
+    #undef _BIG_ENDIAN
+    #define _BIG_ENDIAN 1
+    #undef _ILP32
+    #define _ILP32 1
+    #undef __ATOMIC_ACQUIRE
+    #define __ATOMIC_ACQUIRE 2
+    #undef __ATOMIC_ACQ_REL
+    #define __ATOMIC_ACQ_REL 4
+    #undef __ATOMIC_CONSUME
+    #define __ATOMIC_CONSUME 1
+    #undef __ATOMIC_RELAXED
+    #define __ATOMIC_RELAXED 0
+    #undef __ATOMIC_RELEASE
+    #define __ATOMIC_RELEASE 3
+    #undef __ATOMIC_SEQ_CST
+    #define __ATOMIC_SEQ_CST 5
+    #undef __BIGGEST_ALIGNMENT__
+    #define __BIGGEST_ALIGNMENT__ 16
+    #undef __BIG_ENDIAN__
+    #define __BIG_ENDIAN__ 1
+    #undef __BITINT_MAXWIDTH__
+    #define __BITINT_MAXWIDTH__ 128
+    #undef __BOOL_WIDTH__
+    #define __BOOL_WIDTH__ 8
+    #undef __BYTE_ORDER__
+    #define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
+    #undef __CHAR16_TYPE__
+    #define __CHAR16_TYPE__ unsigned short
+    #undef __CHAR32_TYPE__
+    #define __CHAR32_TYPE__ unsigned int
+    #undef __CHAR_BIT__
+    #define __CHAR_BIT__ 8
+    #undef __CHAR_UNSIGNED__
+    #define __CHAR_UNSIGNED__ 1
+    #undef __CLANG_ATOMIC_BOOL_LOCK_FREE
+    #define __CLANG_ATOMIC_BOOL_LOCK_FREE 2
+    #undef __CLANG_ATOMIC_CHAR16_T_LOCK_FREE
+    #define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 2
+    #undef __CLANG_ATOMIC_CHAR32_T_LOCK_FREE
+    #define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 2
+    #undef __CLANG_ATOMIC_CHAR_LOCK_FREE
+    #define __CLANG_ATOMIC_CHAR_LOCK_FREE 2
+    #undef __CLANG_ATOMIC_INT_LOCK_FREE
+    #define __CLANG_ATOMIC_INT_LOCK_FREE 2
+    #undef __CLANG_ATOMIC_LLONG_LOCK_FREE
+    #define __CLANG_ATOMIC_LLONG_LOCK_FREE 1
+    #undef __CLANG_ATOMIC_LONG_LOCK_FREE
+    #define __CLANG_ATOMIC_LONG_LOCK_FREE 2
+    #undef __CLANG_ATOMIC_POINTER_LOCK_FREE
+    #define __CLANG_ATOMIC_POINTER_LOCK_FREE 2
+    #undef __CLANG_ATOMIC_SHORT_LOCK_FREE
+    #define __CLANG_ATOMIC_SHORT_LOCK_FREE 2
+    #undef __CLANG_ATOMIC_WCHAR_T_LOCK_FREE
+    #define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 2
+    #undef __CONSTANT_CFSTRINGS__
+    #define __CONSTANT_CFSTRINGS__ 1
+    #undef __DBL_DECIMAL_DIG__
+    #define __DBL_DECIMAL_DIG__ 17
+    #undef __DBL_DENORM_MIN__
+    #define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+    #undef __DBL_DIG__
+    #define __DBL_DIG__ 15
+    #undef __DBL_EPSILON__
+    #define __DBL_EPSILON__ 2.2204460492503131e-16
+    #undef __DBL_HAS_DENORM__
+    #define __DBL_HAS_DENORM__ 1
+    #undef __DBL_HAS_INFINITY__
+    #define __DBL_HAS_INFINITY__ 1
+    #undef __DBL_HAS_QUIET_NAN__
+    #define __DBL_HAS_QUIET_NAN__ 1
+    #undef __DBL_MANT_DIG__
+    #define __DBL_MANT_DIG__ 53
+    #undef __DBL_MAX_10_EXP__
+    #define __DBL_MAX_10_EXP__ 308
+    #undef __DBL_MAX_EXP__
+    #define __DBL_MAX_EXP__ 1024
+    #undef __DBL_MAX__
+    #define __DBL_MAX__ 1.7976931348623157e+308
+    #undef __DBL_MIN_10_EXP__
+    #define __DBL_MIN_10_EXP__ (-307)
+    #undef __DBL_MIN_EXP__
+    #define __DBL_MIN_EXP__ (-1021)
+    #undef __DBL_MIN__
+    #define __DBL_MIN__ 2.2250738585072014e-308
+    #undef __DECIMAL_DIG__
+    #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
+    #undef __ELF__
+    #define __ELF__ 1
+    #undef __FINITE_MATH_ONLY__
+    #define __FINITE_MATH_ONLY__ 0
+    #undef __FLT_DECIMAL_DIG__
+    #define __FLT_DECIMAL_DIG__ 9
+    #undef __FLT_DENORM_MIN__
+    #define __FLT_DENORM_MIN__ 1.40129846e-45F
+    #undef __FLT_DIG__
+    #define __FLT_DIG__ 6
+    #undef __FLT_EPSILON__
+    #define __FLT_EPSILON__ 1.19209290e-7F
+    #undef __FLT_HAS_DENORM__
+    #define __FLT_HAS_DENORM__ 1
+    #undef __FLT_HAS_INFINITY__
+    #define __FLT_HAS_INFINITY__ 1
+    #undef __FLT_HAS_QUIET_NAN__
+    #define __FLT_HAS_QUIET_NAN__ 1
+    #undef __FLT_MANT_DIG__
+    #define __FLT_MANT_DIG__ 24
+    #undef __FLT_MAX_10_EXP__
+    #define __FLT_MAX_10_EXP__ 38
+    #undef __FLT_MAX_EXP__
+    #define __FLT_MAX_EXP__ 128
+    #undef __FLT_MAX__
+    #define __FLT_MAX__ 3.40282347e+38F
+    #undef __FLT_MIN_10_EXP__
+    #define __FLT_MIN_10_EXP__ (-37)
+    #undef __FLT_MIN_EXP__
+    #define __FLT_MIN_EXP__ (-125)
+    #undef __FLT_MIN__
+    #define __FLT_MIN__ 1.17549435e-38F
+    #undef __FLT_RADIX__
+    #define __FLT_RADIX__ 2
+    #undef __GCC_ATOMIC_BOOL_LOCK_FREE
+    #define __GCC_ATOMIC_BOOL_LOCK_FREE 2
+    #undef __GCC_ATOMIC_CHAR16_T_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
+    #undef __GCC_ATOMIC_CHAR32_T_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
+    #undef __GCC_ATOMIC_CHAR_LOCK_FREE
+    #define __GCC_ATOMIC_CHAR_LOCK_FREE 2
+    #undef __GCC_ATOMIC_INT_LOCK_FREE
+    #define __GCC_ATOMIC_INT_LOCK_FREE 2
+    #undef __GCC_ATOMIC_LLONG_LOCK_FREE
+    #define __GCC_ATOMIC_LLONG_LOCK_FREE 1
+    #undef __GCC_ATOMIC_LONG_LOCK_FREE
+    #define __GCC_ATOMIC_LONG_LOCK_FREE 2
+    #undef __GCC_ATOMIC_POINTER_LOCK_FREE
+    #define __GCC_ATOMIC_POINTER_LOCK_FREE 2
+    #undef __GCC_ATOMIC_SHORT_LOCK_FREE
+    #define __GCC_ATOMIC_SHORT_LOCK_FREE 2
+    #undef __GCC_ATOMIC_TEST_AND_SET_TRUEVAL
+    #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
+    #undef __GCC_ATOMIC_WCHAR_T_LOCK_FREE
+    #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
+    #undef __GCC_HAVE_DWARF2_CFI_ASM
+    #define __GCC_HAVE_DWARF2_CFI_ASM 1
+    #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
+    #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+    #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
+    #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
+    #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
+    #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
+    #undef __GNUC_MINOR__
+    #define __GNUC_MINOR__ 2
+    #undef __GNUC_PATCHLEVEL__
+    #define __GNUC_PATCHLEVEL__ 1
+    #undef __GNUC_STDC_INLINE__
+    #define __GNUC_STDC_INLINE__ 1
+    #undef __GNUC__
+    #define __GNUC__ 4
+    #undef __GXX_ABI_VERSION
+    #define __GXX_ABI_VERSION 1002
+    #undef __HAVE_BSWAP__
+    #define __HAVE_BSWAP__ 1
+    #undef __ILP32__
+    #define __ILP32__ 1
+    #undef __INT16_C_SUFFIX__
+    #define __INT16_C_SUFFIX__
+    #undef __INT16_FMTd__
+    #define __INT16_FMTd__ "hd"
+    #undef __INT16_FMTi__
+    #define __INT16_FMTi__ "hi"
+    #undef __INT16_MAX__
+    #define __INT16_MAX__ 32767
+    #undef __INT16_TYPE__
+    #define __INT16_TYPE__ short
+    #undef __INT32_C_SUFFIX__
+    #define __INT32_C_SUFFIX__
+    #undef __INT32_FMTd__
+    #define __INT32_FMTd__ "d"
+    #undef __INT32_FMTi__
+    #define __INT32_FMTi__ "i"
+    #undef __INT32_MAX__
+    #define __INT32_MAX__ 2147483647
+    #undef __INT32_TYPE__
+    #define __INT32_TYPE__ int
+    #undef __INT64_C_SUFFIX__
+    #define __INT64_C_SUFFIX__ LL
+    #undef __INT64_FMTd__
+    #define __INT64_FMTd__ "lld"
+    #undef __INT64_FMTi__
+    #define __INT64_FMTi__ "lli"
+    #undef __INT64_MAX__
+    #define __INT64_MAX__ 9223372036854775807LL
+    #undef __INT64_TYPE__
+    #define __INT64_TYPE__ long long int
+    #undef __INT8_C_SUFFIX__
+    #define __INT8_C_SUFFIX__
+    #undef __INT8_FMTd__
+    #define __INT8_FMTd__ "hhd"
+    #undef __INT8_FMTi__
+    #define __INT8_FMTi__ "hhi"
+    #undef __INT8_MAX__
+    #define __INT8_MAX__ 127
+    #undef __INT8_TYPE__
+    #define __INT8_TYPE__ signed char
+    #undef __INTMAX_C_SUFFIX__
+    #define __INTMAX_C_SUFFIX__ LL
+    #undef __INTMAX_FMTd__
+    #define __INTMAX_FMTd__ "lld"
+    #undef __INTMAX_FMTi__
+    #define __INTMAX_FMTi__ "lli"
+    #undef __INTMAX_MAX__
+    #define __INTMAX_MAX__ 9223372036854775807LL
+    #undef __INTMAX_TYPE__
+    #define __INTMAX_TYPE__ long long int
+    #undef __INTMAX_WIDTH__
+    #define __INTMAX_WIDTH__ 64
+    #undef __INTPTR_FMTd__
+    #define __INTPTR_FMTd__ "d"
+    #undef __INTPTR_FMTi__
+    #define __INTPTR_FMTi__ "i"
+    #undef __INTPTR_MAX__
+    #define __INTPTR_MAX__ 2147483647
+    #undef __INTPTR_TYPE__
+    #define __INTPTR_TYPE__ int
+    #undef __INTPTR_WIDTH__
+    #define __INTPTR_WIDTH__ 32
+    #undef __INT_FAST16_FMTd__
+    #define __INT_FAST16_FMTd__ "hd"
+    #undef __INT_FAST16_FMTi__
+    #define __INT_FAST16_FMTi__ "hi"
+    #undef __INT_FAST16_MAX__
+    #define __INT_FAST16_MAX__ 32767
+    #undef __INT_FAST16_TYPE__
+    #define __INT_FAST16_TYPE__ short
+    #undef __INT_FAST16_WIDTH__
+    #define __INT_FAST16_WIDTH__ 16
+    #undef __INT_FAST32_FMTd__
+    #define __INT_FAST32_FMTd__ "d"
+    #undef __INT_FAST32_FMTi__
+    #define __INT_FAST32_FMTi__ "i"
+    #undef __INT_FAST32_MAX__
+    #define __INT_FAST32_MAX__ 2147483647
+    #undef __INT_FAST32_TYPE__
+    #define __INT_FAST32_TYPE__ int
+    #undef __INT_FAST32_WIDTH__
+    #define __INT_FAST32_WIDTH__ 32
+    #undef __INT_FAST64_FMTd__
+    #define __INT_FAST64_FMTd__ "lld"
+    #undef __INT_FAST64_FMTi__
+    #define __INT_FAST64_FMTi__ "lli"
+    #undef __INT_FAST64_MAX__
+    #define __INT_FAST64_MAX__ 9223372036854775807LL
+    #undef __INT_FAST64_TYPE__
+    #define __INT_FAST64_TYPE__ long long int
+    #undef __INT_FAST64_WIDTH__
+    #define __INT_FAST64_WIDTH__ 64
+    #undef __INT_FAST8_FMTd__
+    #define __INT_FAST8_FMTd__ "hhd"
+    #undef __INT_FAST8_FMTi__
+    #define __INT_FAST8_FMTi__ "hhi"
+    #undef __INT_FAST8_MAX__
+    #define __INT_FAST8_MAX__ 127
+    #undef __INT_FAST8_TYPE__
+    #define __INT_FAST8_TYPE__ signed char
+    #undef __INT_FAST8_WIDTH__
+    #define __INT_FAST8_WIDTH__ 8
+    #undef __INT_LEAST16_FMTd__
+    #define __INT_LEAST16_FMTd__ "hd"
+    #undef __INT_LEAST16_FMTi__
+    #define __INT_LEAST16_FMTi__ "hi"
+    #undef __INT_LEAST16_MAX__
+    #define __INT_LEAST16_MAX__ 32767
+    #undef __INT_LEAST16_TYPE__
+    #define __INT_LEAST16_TYPE__ short
+    #undef __INT_LEAST16_WIDTH__
+    #define __INT_LEAST16_WIDTH__ 16
+    #undef __INT_LEAST32_FMTd__
+    #define __INT_LEAST32_FMTd__ "d"
+    #undef __INT_LEAST32_FMTi__
+    #define __INT_LEAST32_FMTi__ "i"
+    #undef __INT_LEAST32_MAX__
+    #define __INT_LEAST32_MAX__ 2147483647
+    #undef __INT_LEAST32_TYPE__
+    #define __INT_LEAST32_TYPE__ int
+    #undef __INT_LEAST32_WIDTH__
+    #define __INT_LEAST32_WIDTH__ 32
+    #undef __INT_LEAST64_FMTd__
+    #define __INT_LEAST64_FMTd__ "lld"
+    #undef __INT_LEAST64_FMTi__
+    #define __INT_LEAST64_FMTi__ "lli"
+    #undef __INT_LEAST64_MAX__
+    #define __INT_LEAST64_MAX__ 9223372036854775807LL
+    #undef __INT_LEAST64_TYPE__
+    #define __INT_LEAST64_TYPE__ long long int
+    #undef __INT_LEAST64_WIDTH__
+    #define __INT_LEAST64_WIDTH__ 64
+    #undef __INT_LEAST8_FMTd__
+    #define __INT_LEAST8_FMTd__ "hhd"
+    #undef __INT_LEAST8_FMTi__
+    #define __INT_LEAST8_FMTi__ "hhi"
+    #undef __INT_LEAST8_MAX__
+    #define __INT_LEAST8_MAX__ 127
+    #undef __INT_LEAST8_TYPE__
+    #define __INT_LEAST8_TYPE__ signed char
+    #undef __INT_LEAST8_WIDTH__
+    #define __INT_LEAST8_WIDTH__ 8
+    #undef __INT_MAX__
+    #define __INT_MAX__ 2147483647
+    #undef __INT_WIDTH__
+    #define __INT_WIDTH__ 32
+    #undef __LDBL_DECIMAL_DIG__
+    #define __LDBL_DECIMAL_DIG__ 33
+    #undef __LDBL_DENORM_MIN__
+    #define __LDBL_DENORM_MIN__ 4.94065645841246544176568792868221e-324L
+    #undef __LDBL_DIG__
+    #define __LDBL_DIG__ 31
+    #undef __LDBL_EPSILON__
+    #define __LDBL_EPSILON__ 4.94065645841246544176568792868221e-324L
+    #undef __LDBL_HAS_DENORM__
+    #define __LDBL_HAS_DENORM__ 1
+    #undef __LDBL_HAS_INFINITY__
+    #define __LDBL_HAS_INFINITY__ 1
+    #undef __LDBL_HAS_QUIET_NAN__
+    #define __LDBL_HAS_QUIET_NAN__ 1
+    #undef __LDBL_MANT_DIG__
+    #define __LDBL_MANT_DIG__ 106
+    #undef __LDBL_MAX_10_EXP__
+    #define __LDBL_MAX_10_EXP__ 308
+    #undef __LDBL_MAX_EXP__
+    #define __LDBL_MAX_EXP__ 1024
+    #undef __LDBL_MAX__
+    #define __LDBL_MAX__ 1.79769313486231580793728971405301e+308L
+    #undef __LDBL_MIN_10_EXP__
+    #define __LDBL_MIN_10_EXP__ (-291)
+    #undef __LDBL_MIN_EXP__
+    #define __LDBL_MIN_EXP__ (-968)
+    #undef __LDBL_MIN__
+    #define __LDBL_MIN__ 2.00416836000897277799610805135016e-292L
+    #undef __LLONG_WIDTH__
+    #define __LLONG_WIDTH__ 64
+    #undef __LONGDOUBLE128
+    #define __LONGDOUBLE128 1
+    #undef __LONG_DOUBLE_128__
+    #define __LONG_DOUBLE_128__ 1
+    #undef __LONG_DOUBLE_IBM128__
+    #define __LONG_DOUBLE_IBM128__ 1
+    #undef __LONG_LONG_MAX__
+    #define __LONG_LONG_MAX__ 9223372036854775807LL
+    #undef __LONG_MAX__
+    #define __LONG_MAX__ 2147483647L
+    #undef __LONG_WIDTH__
+    #define __LONG_WIDTH__ 32
+    #undef __NATURAL_ALIGNMENT__
+    #define __NATURAL_ALIGNMENT__ 1
+    #undef __NO_INLINE__
+    #define __NO_INLINE__ 1
+    #undef __OBJC_BOOL_IS_BOOL
+    #define __OBJC_BOOL_IS_BOOL 0
+    #undef __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES
+    #define __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES 3
+    #undef __OPENCL_MEMORY_SCOPE_DEVICE
+    #define __OPENCL_MEMORY_SCOPE_DEVICE 2
+    #undef __OPENCL_MEMORY_SCOPE_SUB_GROUP
+    #define __OPENCL_MEMORY_SCOPE_SUB_GROUP 4
+    #undef __OPENCL_MEMORY_SCOPE_WORK_GROUP
+    #define __OPENCL_MEMORY_SCOPE_WORK_GROUP 1
+    #undef __OPENCL_MEMORY_SCOPE_WORK_ITEM
+    #define __OPENCL_MEMORY_SCOPE_WORK_ITEM 0
+    #undef __ORDER_BIG_ENDIAN__
+    #define __ORDER_BIG_ENDIAN__ 4321
+    #undef __ORDER_LITTLE_ENDIAN__
+    #define __ORDER_LITTLE_ENDIAN__ 1234
+    #undef __ORDER_PDP_ENDIAN__
+    #define __ORDER_PDP_ENDIAN__ 3412
+    #undef __PIC__
+    #define __PIC__ 2
+    #undef __PIE__
+    #define __PIE__ 2
+    #undef __POINTER_WIDTH__
+    #define __POINTER_WIDTH__ 32
+    #undef __POWERPC__
+    #define __POWERPC__ 1
+    #undef __PPC__
+    #define __PPC__ 1
+    #undef __PRAGMA_REDEFINE_EXTNAME
+    #define __PRAGMA_REDEFINE_EXTNAME 1
+    #undef __PTRDIFF_FMTd__
+    #define __PTRDIFF_FMTd__ "d"
+    #undef __PTRDIFF_FMTi__
+    #define __PTRDIFF_FMTi__ "i"
+    #undef __PTRDIFF_MAX__
+    #define __PTRDIFF_MAX__ 2147483647
+    #undef __PTRDIFF_TYPE__
+    #define __PTRDIFF_TYPE__ int
+    #undef __PTRDIFF_WIDTH__
+    #define __PTRDIFF_WIDTH__ 32
+    #undef __REGISTER_PREFIX__
+    #define __REGISTER_PREFIX__
+    #undef __SCHAR_MAX__
+    #define __SCHAR_MAX__ 127
+    #undef __SHRT_MAX__
+    #define __SHRT_MAX__ 32767
+    #undef __SHRT_WIDTH__
+    #define __SHRT_WIDTH__ 16
+    #undef __SIG_ATOMIC_MAX__
+    #define __SIG_ATOMIC_MAX__ 2147483647
+    #undef __SIG_ATOMIC_WIDTH__
+    #define __SIG_ATOMIC_WIDTH__ 32
+    #undef __SIZEOF_DOUBLE__
+    #define __SIZEOF_DOUBLE__ 8
+    #undef __SIZEOF_FLOAT__
+    #define __SIZEOF_FLOAT__ 4
+    #undef __SIZEOF_INT__
+    #define __SIZEOF_INT__ 4
+    #undef __SIZEOF_LONG_DOUBLE__
+    #define __SIZEOF_LONG_DOUBLE__ 16
+    #undef __SIZEOF_LONG_LONG__
+    #define __SIZEOF_LONG_LONG__ 8
+    #undef __SIZEOF_LONG__
+    #define __SIZEOF_LONG__ 4
+    #undef __SIZEOF_POINTER__
+    #define __SIZEOF_POINTER__ 4
+    #undef __SIZEOF_PTRDIFF_T__
+    #define __SIZEOF_PTRDIFF_T__ 4
+    #undef __SIZEOF_SHORT__
+    #define __SIZEOF_SHORT__ 2
+    #undef __SIZEOF_SIZE_T__
+    #define __SIZEOF_SIZE_T__ 4
+    #undef __SIZEOF_WCHAR_T__
+    #define __SIZEOF_WCHAR_T__ 4
+    #undef __SIZEOF_WINT_T__
+    #define __SIZEOF_WINT_T__ 4
+    #undef __SIZE_FMTX__
+    #define __SIZE_FMTX__ "X"
+    #undef __SIZE_FMTo__
+    #define __SIZE_FMTo__ "o"
+    #undef __SIZE_FMTu__
+    #define __SIZE_FMTu__ "u"
+    #undef __SIZE_FMTx__
+    #define __SIZE_FMTx__ "x"
+    #undef __SIZE_MAX__
+    #define __SIZE_MAX__ 4294967295U
+    #undef __SIZE_TYPE__
+    #define __SIZE_TYPE__ unsigned int
+    #undef __SIZE_WIDTH__
+    #define __SIZE_WIDTH__ 32
+    #undef __SSP_STRONG__
+    #define __SSP_STRONG__ 2
+    #undef __UINT16_C_SUFFIX__
+    #define __UINT16_C_SUFFIX__
+    #undef __UINT16_FMTX__
+    #define __UINT16_FMTX__ "hX"
+    #undef __UINT16_FMTo__
+    #define __UINT16_FMTo__ "ho"
+    #undef __UINT16_FMTu__
+    #define __UINT16_FMTu__ "hu"
+    #undef __UINT16_FMTx__
+    #define __UINT16_FMTx__ "hx"
+    #undef __UINT16_MAX__
+    #define __UINT16_MAX__ 65535
+    #undef __UINT16_TYPE__
+    #define __UINT16_TYPE__ unsigned short
+    #undef __UINT32_C_SUFFIX__
+    #define __UINT32_C_SUFFIX__ U
+    #undef __UINT32_FMTX__
+    #define __UINT32_FMTX__ "X"
+    #undef __UINT32_FMTo__
+    #define __UINT32_FMTo__ "o"
+    #undef __UINT32_FMTu__
+    #define __UINT32_FMTu__ "u"
+    #undef __UINT32_FMTx__
+    #define __UINT32_FMTx__ "x"
+    #undef __UINT32_MAX__
+    #define __UINT32_MAX__ 4294967295U
+    #undef __UINT32_TYPE__
+    #define __UINT32_TYPE__ unsigned int
+    #undef __UINT64_C_SUFFIX__
+    #define __UINT64_C_SUFFIX__ ULL
+    #undef __UINT64_FMTX__
+    #define __UINT64_FMTX__ "llX"
+    #undef __UINT64_FMTo__
+    #define __UINT64_FMTo__ "llo"
+    #undef __UINT64_FMTu__
+    #define __UINT64_FMTu__ "llu"
+    #undef __UINT64_FMTx__
+    #define __UINT64_FMTx__ "llx"
+    #undef __UINT64_MAX__
+    #define __UINT64_MAX__ 18446744073709551615ULL
+    #undef __UINT64_TYPE__
+    #define __UINT64_TYPE__ long long unsigned int
+    #undef __UINT8_C_SUFFIX__
+    #define __UINT8_C_SUFFIX__
+    #undef __UINT8_FMTX__
+    #define __UINT8_FMTX__ "hhX"
+    #undef __UINT8_FMTo__
+    #define __UINT8_FMTo__ "hho"
+    #undef __UINT8_FMTu__
+    #define __UINT8_FMTu__ "hhu"
+    #undef __UINT8_FMTx__
+    #define __UINT8_FMTx__ "hhx"
+    #undef __UINT8_MAX__
+    #define __UINT8_MAX__ 255
+    #undef __UINT8_TYPE__
+    #define __UINT8_TYPE__ unsigned char
+    #undef __UINTMAX_C_SUFFIX__
+    #define __UINTMAX_C_SUFFIX__ ULL
+    #undef __UINTMAX_FMTX__
+    #define __UINTMAX_FMTX__ "llX"
+    #undef __UINTMAX_FMTo__
+    #define __UINTMAX_FMTo__ "llo"
+    #undef __UINTMAX_FMTu__
+    #define __UINTMAX_FMTu__ "llu"
+    #undef __UINTMAX_FMTx__
+    #define __UINTMAX_FMTx__ "llx"
+    #undef __UINTMAX_MAX__
+    #define __UINTMAX_MAX__ 18446744073709551615ULL
+    #undef __UINTMAX_TYPE__
+    #define __UINTMAX_TYPE__ long long unsigned int
+    #undef __UINTMAX_WIDTH__
+    #define __UINTMAX_WIDTH__ 64
+    #undef __UINTPTR_FMTX__
+    #define __UINTPTR_FMTX__ "X"
+    #undef __UINTPTR_FMTo__
+    #define __UINTPTR_FMTo__ "o"
+    #undef __UINTPTR_FMTu__
+    #define __UINTPTR_FMTu__ "u"
+    #undef __UINTPTR_FMTx__
+    #define __UINTPTR_FMTx__ "x"
+    #undef __UINTPTR_MAX__
+    #define __UINTPTR_MAX__ 4294967295U
+    #undef __UINTPTR_TYPE__
+    #define __UINTPTR_TYPE__ unsigned int
+    #undef __UINTPTR_WIDTH__
+    #define __UINTPTR_WIDTH__ 32
+    #undef __UINT_FAST16_FMTX__
+    #define __UINT_FAST16_FMTX__ "hX"
+    #undef __UINT_FAST16_FMTo__
+    #define __UINT_FAST16_FMTo__ "ho"
+    #undef __UINT_FAST16_FMTu__
+    #define __UINT_FAST16_FMTu__ "hu"
+    #undef __UINT_FAST16_FMTx__
+    #define __UINT_FAST16_FMTx__ "hx"
+    #undef __UINT_FAST16_MAX__
+    #define __UINT_FAST16_MAX__ 65535
+    #undef __UINT_FAST16_TYPE__
+    #define __UINT_FAST16_TYPE__ unsigned short
+    #undef __UINT_FAST32_FMTX__
+    #define __UINT_FAST32_FMTX__ "X"
+    #undef __UINT_FAST32_FMTo__
+    #define __UINT_FAST32_FMTo__ "o"
+    #undef __UINT_FAST32_FMTu__
+    #define __UINT_FAST32_FMTu__ "u"
+    #undef __UINT_FAST32_FMTx__
+    #define __UINT_FAST32_FMTx__ "x"
+    #undef __UINT_FAST32_MAX__
+    #define __UINT_FAST32_MAX__ 4294967295U
+    #undef __UINT_FAST32_TYPE__
+    #define __UINT_FAST32_TYPE__ unsigned int
+    #undef __UINT_FAST64_FMTX__
+    #define __UINT_FAST64_FMTX__ "llX"
+    #undef __UINT_FAST64_FMTo__
+    #define __UINT_FAST64_FMTo__ "llo"
+    #undef __UINT_FAST64_FMTu__
+    #define __UINT_FAST64_FMTu__ "llu"
+    #undef __UINT_FAST64_FMTx__
+    #define __UINT_FAST64_FMTx__ "llx"
+    #undef __UINT_FAST64_MAX__
+    #define __UINT_FAST64_MAX__ 18446744073709551615ULL
+    #undef __UINT_FAST64_TYPE__
+    #define __UINT_FAST64_TYPE__ long long unsigned int
+    #undef __UINT_FAST8_FMTX__
+    #define __UINT_FAST8_FMTX__ "hhX"
+    #undef __UINT_FAST8_FMTo__
+    #define __UINT_FAST8_FMTo__ "hho"
+    #undef __UINT_FAST8_FMTu__
+    #define __UINT_FAST8_FMTu__ "hhu"
+    #undef __UINT_FAST8_FMTx__
+    #define __UINT_FAST8_FMTx__ "hhx"
+    #undef __UINT_FAST8_MAX__
+    #define __UINT_FAST8_MAX__ 255
+    #undef __UINT_FAST8_TYPE__
+    #define __UINT_FAST8_TYPE__ unsigned char
+    #undef __UINT_LEAST16_FMTX__
+    #define __UINT_LEAST16_FMTX__ "hX"
+    #undef __UINT_LEAST16_FMTo__
+    #define __UINT_LEAST16_FMTo__ "ho"
+    #undef __UINT_LEAST16_FMTu__
+    #define __UINT_LEAST16_FMTu__ "hu"
+    #undef __UINT_LEAST16_FMTx__
+    #define __UINT_LEAST16_FMTx__ "hx"
+    #undef __UINT_LEAST16_MAX__
+    #define __UINT_LEAST16_MAX__ 65535
+    #undef __UINT_LEAST16_TYPE__
+    #define __UINT_LEAST16_TYPE__ unsigned short
+    #undef __UINT_LEAST32_FMTX__
+    #define __UINT_LEAST32_FMTX__ "X"
+    #undef __UINT_LEAST32_FMTo__
+    #define __UINT_LEAST32_FMTo__ "o"
+    #undef __UINT_LEAST32_FMTu__
+    #define __UINT_LEAST32_FMTu__ "u"
+    #undef __UINT_LEAST32_FMTx__
+    #define __UINT_LEAST32_FMTx__ "x"
+    #undef __UINT_LEAST32_MAX__
+    #define __UINT_LEAST32_MAX__ 4294967295U
+    #undef __UINT_LEAST32_TYPE__
+    #define __UINT_LEAST32_TYPE__ unsigned int
+    #undef __UINT_LEAST64_FMTX__
+    #define __UINT_LEAST64_FMTX__ "llX"
+    #undef __UINT_LEAST64_FMTo__
+    #define __UINT_LEAST64_FMTo__ "llo"
+    #undef __UINT_LEAST64_FMTu__
+    #define __UINT_LEAST64_FMTu__ "llu"
+    #undef __UINT_LEAST64_FMTx__
+    #define __UINT_LEAST64_FMTx__ "llx"
+    #undef __UINT_LEAST64_MAX__
+    #define __UINT_LEAST64_MAX__ 18446744073709551615ULL
+    #undef __UINT_LEAST64_TYPE__
+    #define __UINT_LEAST64_TYPE__ long long unsigned int
+    #undef __UINT_LEAST8_FMTX__
+    #define __UINT_LEAST8_FMTX__ "hhX"
+    #undef __UINT_LEAST8_FMTo__
+    #define __UINT_LEAST8_FMTo__ "hho"
+    #undef __UINT_LEAST8_FMTu__
+    #define __UINT_LEAST8_FMTu__ "hhu"
+    #undef __UINT_LEAST8_FMTx__
+    #define __UINT_LEAST8_FMTx__ "hhx"
+    #undef __UINT_LEAST8_MAX__
+    #define __UINT_LEAST8_MAX__ 255
+    #undef __UINT_LEAST8_TYPE__
+    #define __UINT_LEAST8_TYPE__ unsigned char
+    #undef __USER_LABEL_PREFIX__
+    #define __USER_LABEL_PREFIX__
+    #undef __VERSION__
+    #define __VERSION__ "Clang 15.0.7"
+    #undef __WCHAR_MAX__
+    #define __WCHAR_MAX__ 2147483647
+    #undef __WCHAR_TYPE__
+    #define __WCHAR_TYPE__ int
+    #undef __WCHAR_WIDTH__
+    #define __WCHAR_WIDTH__ 32
+    #undef __WINT_MAX__
+    #define __WINT_MAX__ 4294967295U
+    #undef __WINT_TYPE__
+    #define __WINT_TYPE__ unsigned int
+    #undef __WINT_UNSIGNED__
+    #define __WINT_UNSIGNED__ 1
+    #undef __WINT_WIDTH__
+    #define __WINT_WIDTH__ 32
+    #undef __abs
+    #define __abs __builtin_abs
+    #undef __addex
+    #define __addex __builtin_ppc_addex
+    #undef __alignx
+    #define __alignx __builtin_ppc_alignx
+    #undef __alloca
+    #define __alloca __builtin_alloca
+    #undef __bcopy
+    #define __bcopy bcopy
+    #undef __bpermd
+    #define __bpermd __builtin_bpermd
+    #undef __builtin_maxfe
+    #define __builtin_maxfe __builtin_ppc_maxfe
+    #undef __builtin_maxfl
+    #define __builtin_maxfl __builtin_ppc_maxfl
+    #undef __builtin_maxfs
+    #define __builtin_maxfs __builtin_ppc_maxfs
+    #undef __builtin_minfe
+    #define __builtin_minfe __builtin_ppc_minfe
+    #undef __builtin_minfl
+    #define __builtin_minfl __builtin_ppc_minfl
+    #undef __builtin_minfs
+    #define __builtin_minfs __builtin_ppc_minfs
+    #undef __clang__
+    #define __clang__ 1
+    #undef __clang_literal_encoding__
+    #define __clang_literal_encoding__ "UTF-8"
+    #undef __clang_major__
+    #define __clang_major__ 15
+    #undef __clang_minor__
+    #define __clang_minor__ 0
+    #undef __clang_patchlevel__
+    #define __clang_patchlevel__ 7
+    #undef __clang_version__
+    #define __clang_version__ "15.0.7 "
+    #undef __clang_wide_literal_encoding__
+    #define __clang_wide_literal_encoding__ "UTF-32"
+    #undef __cmpb
+    #define __cmpb __builtin_ppc_cmpb
+    #undef __cmpeqb
+    #define __cmpeqb __builtin_ppc_cmpeqb
+    #undef __cmplx
+    #define __cmplx __builtin_complex
+    #undef __cmplxf
+    #define __cmplxf __builtin_complex
+    #undef __cmplxl
+    #define __cmplxl __builtin_complex
+    #undef __cmprb
+    #define __cmprb __builtin_ppc_cmprb
+    #undef __cntlz4
+    #define __cntlz4 __builtin_clz
+    #undef __cntlz8
+    #define __cntlz8 __builtin_clzll
+    #undef __cnttz4
+    #define __cnttz4 __builtin_ctz
+    #undef __cnttz8
+    #define __cnttz8 __builtin_ctzll
+    #undef __compare_and_swap
+    #define __compare_and_swap __builtin_ppc_compare_and_swap
+    #undef __compare_and_swaplp
+    #define __compare_and_swaplp __builtin_ppc_compare_and_swaplp
+    #undef __compare_exp_eq
+    #define __compare_exp_eq __builtin_ppc_compare_exp_eq
+    #undef __compare_exp_gt
+    #define __compare_exp_gt __builtin_ppc_compare_exp_gt
+    #undef __compare_exp_lt
+    #define __compare_exp_lt __builtin_ppc_compare_exp_lt
+    #undef __compare_exp_uo
+    #define __compare_exp_uo __builtin_ppc_compare_exp_uo
+    #undef __darn
+    #define __darn __builtin_darn
+    #undef __darn_32
+    #define __darn_32 __builtin_darn_32
+    #undef __darn_raw
+    #define __darn_raw __builtin_darn_raw
+    #undef __dcbf
+    #define __dcbf __builtin_dcbf
+    #undef __dcbfl
+    #define __dcbfl __builtin_ppc_dcbfl
+    #undef __dcbflp
+    #define __dcbflp __builtin_ppc_dcbflp
+    #undef __dcbst
+    #define __dcbst __builtin_ppc_dcbst
+    #undef __dcbt
+    #define __dcbt __builtin_ppc_dcbt
+    #undef __dcbtst
+    #define __dcbtst __builtin_ppc_dcbtst
+    #undef __dcbtstt
+    #define __dcbtstt __builtin_ppc_dcbtstt
+    #undef __dcbtt
+    #define __dcbtt __builtin_ppc_dcbtt
+    #undef __dcbz
+    #define __dcbz __builtin_ppc_dcbz
+    #undef __divde
+    #define __divde __builtin_divde
+    #undef __divdeu
+    #define __divdeu __builtin_divdeu
+    #undef __divwe
+    #define __divwe __builtin_divwe
+    #undef __divweu
+    #define __divweu __builtin_divweu
+    #undef __eieio
+    #define __eieio __builtin_ppc_eieio
+    #undef __extract_exp
+    #define __extract_exp __builtin_ppc_extract_exp
+    #undef __extract_sig
+    #define __extract_sig __builtin_ppc_extract_sig
+    #undef __fcfid
+    #define __fcfid __builtin_ppc_fcfid
+    #undef __fcfud
+    #define __fcfud __builtin_ppc_fcfud
+    #undef __fctid
+    #define __fctid __builtin_ppc_fctid
+    #undef __fctidz
+    #define __fctidz __builtin_ppc_fctidz
+    #undef __fctiw
+    #define __fctiw __builtin_ppc_fctiw
+    #undef __fctiwz
+    #define __fctiwz __builtin_ppc_fctiwz
+    #undef __fctudz
+    #define __fctudz __builtin_ppc_fctudz
+    #undef __fctuwz
+    #define __fctuwz __builtin_ppc_fctuwz
+    #undef __fetch_and_add
+    #define __fetch_and_add __builtin_ppc_fetch_and_add
+    #undef __fetch_and_addlp
+    #define __fetch_and_addlp __builtin_ppc_fetch_and_addlp
+    #undef __fetch_and_and
+    #define __fetch_and_and __builtin_ppc_fetch_and_and
+    #undef __fetch_and_andlp
+    #define __fetch_and_andlp __builtin_ppc_fetch_and_andlp
+    #undef __fetch_and_or
+    #define __fetch_and_or __builtin_ppc_fetch_and_or
+    #undef __fetch_and_orlp
+    #define __fetch_and_orlp __builtin_ppc_fetch_and_orlp
+    #undef __fetch_and_swap
+    #define __fetch_and_swap __builtin_ppc_fetch_and_swap
+    #undef __fetch_and_swaplp
+    #define __fetch_and_swaplp __builtin_ppc_fetch_and_swaplp
+    #undef __fmadd
+    #define __fmadd __builtin_fma
+    #undef __fmadds
+    #define __fmadds __builtin_fmaf
+    #undef __fmsub
+    #define __fmsub __builtin_ppc_fmsub
+    #undef __fmsubs
+    #define __fmsubs __builtin_ppc_fmsubs
+    #undef __fnabs
+    #define __fnabs __builtin_ppc_fnabs
+    #undef __fnabss
+    #define __fnabss __builtin_ppc_fnabss
+    #undef __fnmadd
+    #define __fnmadd __builtin_ppc_fnmadd
+    #undef __fnmadds
+    #define __fnmadds __builtin_ppc_fnmadds
+    #undef __fnmsub
+    #define __fnmsub __builtin_ppc_fnmsub
+    #undef __fnmsubs
+    #define __fnmsubs __builtin_ppc_fnmsubs
+    #undef __fre
+    #define __fre __builtin_ppc_fre
+    #undef __fres
+    #define __fres __builtin_ppc_fres
+    #undef __fric
+    #define __fric __builtin_ppc_fric
+    #undef __frim
+    #define __frim __builtin_ppc_frim
+    #undef __frims
+    #define __frims __builtin_ppc_frims
+    #undef __frin
+    #define __frin __builtin_ppc_frin
+    #undef __frins
+    #define __frins __builtin_ppc_frins
+    #undef __frip
+    #define __frip __builtin_ppc_frip
+    #undef __frips
+    #define __frips __builtin_ppc_frips
+    #undef __friz
+    #define __friz __builtin_ppc_friz
+    #undef __frizs
+    #define __frizs __builtin_ppc_frizs
+    #undef __frsqrte
+    #define __frsqrte __builtin_ppc_frsqrte
+    #undef __frsqrtes
+    #define __frsqrtes __builtin_ppc_frsqrtes
+    #undef __fsel
+    #define __fsel __builtin_ppc_fsel
+    #undef __fsels
+    #define __fsels __builtin_ppc_fsels
+    #undef __fsqrt
+    #define __fsqrt __builtin_ppc_fsqrt
+    #undef __fsqrts
+    #define __fsqrts __builtin_ppc_fsqrts
+    #undef __gnu_linux__
+    #define __gnu_linux__ 1
+    #undef __icbt
+    #define __icbt __builtin_ppc_icbt
+    #undef __insert_exp
+    #define __insert_exp __builtin_ppc_insert_exp
+    #undef __iospace_eieio
+    #define __iospace_eieio __builtin_ppc_iospace_eieio
+    #undef __iospace_lwsync
+    #define __iospace_lwsync __builtin_ppc_iospace_lwsync
+    #undef __iospace_sync
+    #define __iospace_sync __builtin_ppc_iospace_sync
+    #undef __isync
+    #define __isync __builtin_ppc_isync
+    #undef __labs
+    #define __labs __builtin_labs
+    #undef __lbarx
+    #define __lbarx __builtin_ppc_lbarx
+    #undef __ldarx
+    #define __ldarx __builtin_ppc_ldarx
+    #undef __lharx
+    #define __lharx __builtin_ppc_lharx
+    #undef __linux
+    #define __linux 1
+    #undef __linux__
+    #define __linux__ 1
+    #undef __llabs
+    #define __llabs __builtin_llabs
+    #undef __llvm__
+    #define __llvm__ 1
+    #undef __load2r
+    #define __load2r __builtin_ppc_load2r
+    #undef __load4r
+    #define __load4r __builtin_ppc_load4r
+    #undef __load8r
+    #define __load8r __builtin_ppc_load8r
+    #undef __lwarx
+    #define __lwarx __builtin_ppc_lwarx
+    #undef __lwsync
+    #define __lwsync __builtin_ppc_lwsync
+    #undef __maddhd
+    #define __maddhd __builtin_ppc_maddhd
+    #undef __maddhdu
+    #define __maddhdu __builtin_ppc_maddhdu
+    #undef __maddld
+    #define __maddld __builtin_ppc_maddld
+    #undef __mfmsr
+    #define __mfmsr __builtin_ppc_mfmsr
+    #undef __mfspr
+    #define __mfspr __builtin_ppc_mfspr
+    #undef __mftbu
+    #define __mftbu __builtin_ppc_mftbu
+    #undef __mtfsb0
+    #define __mtfsb0 __builtin_ppc_mtfsb0
+    #undef __mtfsb1
+    #define __mtfsb1 __builtin_ppc_mtfsb1
+    #undef __mtfsf
+    #define __mtfsf __builtin_ppc_mtfsf
+    #undef __mtfsfi
+    #define __mtfsfi __builtin_ppc_mtfsfi
+    #undef __mtmsr
+    #define __mtmsr __builtin_ppc_mtmsr
+    #undef __mtspr
+    #define __mtspr __builtin_ppc_mtspr
+    #undef __mulhd
+    #define __mulhd __builtin_ppc_mulhd
+    #undef __mulhdu
+    #define __mulhdu __builtin_ppc_mulhdu
+    #undef __mulhw
+    #define __mulhw __builtin_ppc_mulhw
+    #undef __mulhwu
+    #define __mulhwu __builtin_ppc_mulhwu
+    #undef __pic__
+    #define __pic__ 2
+    #undef __pie__
+    #define __pie__ 2
+    #undef __popcnt4
+    #define __popcnt4 __builtin_popcount
+    #undef __popcnt8
+    #define __popcnt8 __builtin_popcountll
+    #undef __popcntb
+    #define __popcntb __builtin_ppc_popcntb
+    #undef __poppar4
+    #define __poppar4 __builtin_ppc_poppar4
+    #undef __poppar8
+    #define __poppar8 __builtin_ppc_poppar8
+    #undef __powerpc__
+    #define __powerpc__ 1
+    #undef __ppc__
+    #define __ppc__ 1
+    #undef __rdlam
+    #define __rdlam __builtin_ppc_rdlam
+    #undef __readflm
+    #define __readflm __builtin_readflm
+    #undef __rldimi
+    #define __rldimi __builtin_ppc_rldimi
+    #undef __rlwimi
+    #define __rlwimi __builtin_ppc_rlwimi
+    #undef __rlwnm
+    #define __rlwnm __builtin_ppc_rlwnm
+    #undef __rotatel4
+    #define __rotatel4 __builtin_rotateleft32
+    #undef __rotatel8
+    #define __rotatel8 __builtin_rotateleft64
+    #undef __setb
+    #define __setb __builtin_ppc_setb
+    #undef __setflm
+    #define __setflm __builtin_setflm
+    #undef __setrnd
+    #define __setrnd __builtin_setrnd
+    #undef __stbcx
+    #define __stbcx __builtin_ppc_stbcx
+    #undef __stdcx
+    #define __stdcx __builtin_ppc_stdcx
+    #undef __stfiw
+    #define __stfiw __builtin_ppc_stfiw
+    #undef __sthcx
+    #define __sthcx __builtin_ppc_sthcx
+    #undef __store2r
+    #define __store2r __builtin_ppc_store2r
+    #undef __store4r
+    #define __store4r __builtin_ppc_store4r
+    #undef __store8r
+    #define __store8r __builtin_ppc_store8r
+    #undef __stwcx
+    #define __stwcx __builtin_ppc_stwcx
+    #undef __swdiv
+    #define __swdiv __builtin_ppc_swdiv
+    #undef __swdiv_nochk
+    #define __swdiv_nochk __builtin_ppc_swdiv_nochk
+    #undef __swdivs
+    #define __swdivs __builtin_ppc_swdivs
+    #undef __swdivs_nochk
+    #define __swdivs_nochk __builtin_ppc_swdivs_nochk
+    #undef __sync
+    #define __sync __builtin_ppc_sync
+    #undef __tdw
+    #define __tdw __builtin_ppc_tdw
+    #undef __test_data_class
+    #define __test_data_class __builtin_ppc_test_data_class
+    #undef __trap
+    #define __trap __builtin_ppc_trap
+    #undef __trapd
+    #define __trapd __builtin_ppc_trapd
+    #undef __tw
+    #define __tw __builtin_ppc_tw
+    #undef __unix
+    #define __unix 1
+    #undef __unix__
+    #define __unix__ 1
+    #undef __vcipher
+    #define __vcipher __builtin_altivec_crypto_vcipher
+    #undef __vcipherlast
+    #define __vcipherlast __builtin_altivec_crypto_vcipherlast
+    #undef __vncipher
+    #define __vncipher __builtin_altivec_crypto_vncipher
+    #undef __vncipherlast
+    #define __vncipherlast __builtin_altivec_crypto_vncipherlast
+    #undef __vpermxor
+    #define __vpermxor __builtin_altivec_crypto_vpermxor
+    #undef __vpmsumb
+    #define __vpmsumb __builtin_altivec_crypto_vpmsumb
+    #undef __vpmsumd
+    #define __vpmsumd __builtin_altivec_crypto_vpmsumd
+    #undef __vpmsumh
+    #define __vpmsumh __builtin_altivec_crypto_vpmsumh
+    #undef __vpmsumw
+    #define __vpmsumw __builtin_altivec_crypto_vpmsumw
+    #undef linux
+    #define linux 1
+    #undef unix
+    #define unix 1
+eof: (-1)
+errno:
+    e2big: '7'
+    eacces: '13'
+    eaddrinuse: '98'
+    eaddrnotavail: '99'
+    eafnosupport: '97'
+    eagain: '11'
+    ealready: '114'
+    ebade: '52'
+    ebadf: '9'
+    ebadfd: '77'
+    ebadmsg: '74'
+    ebadr: '53'
+    ebadrqc: '56'
+    ebadslt: '57'
+    ebusy: '16'
+    ecanceled: '125'
+    echild: '10'
+    echrng: '44'
+    ecomm: '70'
+    econnaborted: '103'
+    econnrefused: '111'
+    econnreset: '104'
+    edeadlk: '35'
+    edeadlock: '35'
+    edestaddrreq: '89'
+    edom: '33'
+    edquot: '122'
+    eexist: '17'
+    efault: '14'
+    efbig: '27'
+    ehostdown: '112'
+    ehostunreach: '113'
+    eidrm: '43'
+    eilseq: '84'
+    einprogress: '115'
+    eintr: '4'
+    einval: '22'
+    eio: '5'
+    eisconn: '106'
+    eisdir: '21'
+    eisnam: '120'
+    ekeyexpired: '127'
+    ekeyrejected: '129'
+    ekeyrevoked: '128'
+    el2hlt: '51'
+    el2nsync: '45'
+    el3hlt: '46'
+    el3rst: '47'
+    elibacc: '79'
+    elibbad: '80'
+    elibexec: '83'
+    elibmax: '82'
+    elibscn: '81'
+    eloop: '40'
+    emediumtype: '124'
+    emfile: '24'
+    emlink: '31'
+    emsgsize: '90'
+    emultihop: '72'
+    enametoolong: '36'
+    enetdown: '100'
+    enetreset: '102'
+    enetunreach: '101'
+    enfile: '23'
+    enobufs: '105'
+    enodata: '61'
+    enodev: '19'
+    enoent: '2'
+    enoexec: '8'
+    enokey: '126'
+    enolck: '37'
+    enolink: '67'
+    enomedium: '123'
+    enomem: '12'
+    enomsg: '42'
+    enonet: '64'
+    enopkg: '65'
+    enoprotoopt: '92'
+    enospc: '28'
+    enosr: '63'
+    enostr: '60'
+    enosys: '38'
+    enotblk: '15'
+    enotconn: '107'
+    enotdir: '20'
+    enotempty: '39'
+    enotrecoverable: '131'
+    enotsock: '88'
+    enotsup: '95'
+    enotty: '25'
+    enotuniq: '76'
+    enxio: '6'
+    eopnotsupp: '95'
+    eoverflow: '75'
+    eownerdead: '130'
+    eperm: '1'
+    epfnosupport: '96'
+    epipe: '32'
+    eproto: '71'
+    eprotonosupport: '93'
+    eprototype: '91'
+    erange: '34'
+    eremchg: '78'
+    eremote: '66'
+    eremoteio: '121'
+    erestart: '85'
+    erofs: '30'
+    eshutdown: '108'
+    esocktnosupport: '94'
+    espipe: '29'
+    esrch: '3'
+    estale: '116'
+    estrpipe: '86'
+    etime: '62'
+    etimedout: '110'
+    etxtbsy: '26'
+    euclean: '117'
+    eunatch: '49'
+    eusers: '87'
+    ewouldblock: '11'
+    exdev: '18'
+    exfull: '54'
+filename_max: '4096'
+fopen_max: '16'
+has__builtin_va_list: true
+host_name_max: '64'
+int_fast16_t: int
+int_fast32_t: int
+int_fast64_t: long long
+int_fast8_t: signed char
+intptr_t: int
+l_tmpnam: '20'
+little_endian: false
+machdep_name: machdep_ppc_32
+mb_cur_max: ((size_t)16)
+nsig: (64 + 1)
+path_max: '4096'
+posix_version: 200809L
+ptrdiff_t: int
+rand_max: '2147483647'
+sig_atomic_t: int
+size_t: unsigned int
+sizeof_double: 8
+sizeof_float: 4
+sizeof_fun: 1
+sizeof_int: 4
+sizeof_long: 4
+sizeof_longdouble: 16
+sizeof_longlong: 8
+sizeof_ptr: 4
+sizeof_short: 2
+sizeof_void: 1
+ssize_t: int
+time_t: long
+tmp_max: '238328'
+tty_name_max: '32'
+uint_fast16_t: unsigned int
+uint_fast32_t: unsigned int
+uint_fast64_t: unsigned long long
+uint_fast8_t: unsigned char
+uintptr_t: unsigned int
+version: clang version 15.0.7
+wchar_t: int
+weof: (0xffffffffu)
+wint_t: unsigned int
+wordsize: '32'
diff --git a/share/machdeps/machdep_x86_16.yaml b/share/machdeps/machdep_x86_16.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..70f9b4bae3ca3d9ef817a5e5b66821de0120e44a
--- /dev/null
+++ b/share/machdeps/machdep_x86_16.yaml
@@ -0,0 +1,886 @@
+alignof_aligned: 8
+alignof_double: 8
+alignof_float: 2
+alignof_fun: -1
+alignof_int: 2
+alignof_long: 4
+alignof_longdouble: 16
+alignof_longlong: 4
+alignof_ptr: 4
+alignof_short: 2
+alignof_str: 1
+char_is_unsigned: false
+compiler: generic
+cpp_arch_flags:
+- -m16
+
+# adapted from the builtin macros of gcc_x86_32
+custom_defs: |
+    #undef __SSP_STRONG__
+    #define __SSP_STRONG__ 3
+    #undef __DBL_MIN_EXP__
+    #define __DBL_MIN_EXP__ (-1021)
+    #undef __UINT_LEAST16_MAX__
+    #define __UINT_LEAST16_MAX__ 0xffff
+    #undef __FLT16_HAS_QUIET_NAN__
+    #define __FLT16_HAS_QUIET_NAN__ 1
+    #undef __ATOMIC_ACQUIRE
+    #define __ATOMIC_ACQUIRE 2
+    #undef __FLT128_MAX_10_EXP__
+    #define __FLT128_MAX_10_EXP__ 4932
+    #undef __FLT_MIN__
+    #define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F
+    #undef __UINT_LEAST8_TYPE__
+    #define __UINT_LEAST8_TYPE__ unsigned char
+    #undef __SIZEOF_FLOAT80__
+    #define __SIZEOF_FLOAT80__ 12
+    #undef __INTMAX_C
+    #define __INTMAX_C(c) c ## LL
+    #undef __CHAR_BIT__
+    #define __CHAR_BIT__ 8
+    #undef __UINT8_MAX__
+    #define __UINT8_MAX__ 0xff
+    #undef __SCHAR_WIDTH__
+    #define __SCHAR_WIDTH__ 8
+    #undef __WINT_MAX__
+    #define __WINT_MAX__ 0xffffffffU
+    #undef __FLT32_MIN_EXP__
+    #define __FLT32_MIN_EXP__ (-125)
+    #undef __ORDER_LITTLE_ENDIAN__
+    #define __ORDER_LITTLE_ENDIAN__ 1234
+    #undef __SIZE_MAX__
+    #define __SIZE_MAX__ 0xffffffffU
+    #undef __WCHAR_MAX__
+    #define __WCHAR_MAX__ 0x7fffffffL
+    #undef __FLT32X_DECIMAL_DIG__
+    #define __FLT32X_DECIMAL_DIG__ 17
+    #undef __FLT_EVAL_METHOD__
+    #define __FLT_EVAL_METHOD__ 2
+    #undef __FLT64_DECIMAL_DIG__
+    #define __FLT64_DECIMAL_DIG__ 17
+    #undef __UINT_FAST64_MAX__
+    #define __UINT_FAST64_MAX__ 0xffffffffffffffffULL
+    #undef __SIG_ATOMIC_TYPE__
+    #define __SIG_ATOMIC_TYPE__ int
+    #undef __DBL_MIN_10_EXP__
+    #define __DBL_MIN_10_EXP__ (-307)
+    #undef __FINITE_MATH_ONLY__
+    #define __FINITE_MATH_ONLY__ 0
+    #undef __FLT32X_MAX_EXP__
+    #define __FLT32X_MAX_EXP__ 1024
+    #undef __FLT32_HAS_DENORM__
+    #define __FLT32_HAS_DENORM__ 1
+    #undef __UINT_FAST8_MAX__
+    #define __UINT_FAST8_MAX__ 0xff
+    #undef __FLT32_MAX_10_EXP__
+    #define __FLT32_MAX_10_EXP__ 38
+    #undef __DEC64_MAX_EXP__
+    #define __DEC64_MAX_EXP__ 385
+    #undef __INT8_C
+    #define __INT8_C(c) c
+    #undef __INT_LEAST8_WIDTH__
+    #define __INT_LEAST8_WIDTH__ 8
+    #undef __UINT_LEAST64_MAX__
+    #define __UINT_LEAST64_MAX__ 0xffffffffffffffffULL
+    #undef __SHRT_MAX__
+    #define __SHRT_MAX__ 0x7fff
+    #undef __LDBL_MAX__
+    #define __LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L
+    #undef __FLT64X_MAX_10_EXP__
+    #define __FLT64X_MAX_10_EXP__ 4932
+    #undef __LDBL_IS_IEC_60559__
+    #define __LDBL_IS_IEC_60559__ 2
+    #undef __FLT64X_HAS_QUIET_NAN__
+    #define __FLT64X_HAS_QUIET_NAN__ 1
+    #undef __UINT_LEAST8_MAX__
+    #define __UINT_LEAST8_MAX__ 0xff
+    #undef __LAHF_SAHF__
+    #define __LAHF_SAHF__ 1
+    #undef __FLT128_DENORM_MIN__
+    #define __FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128
+    #undef __UINTMAX_TYPE__
+    #define __UINTMAX_TYPE__ long long unsigned int
+    #undef __linux
+    #define __linux 1
+    #undef __DEC32_EPSILON__
+    #define __DEC32_EPSILON__ 1E-6DF
+    #undef __FLT_EVAL_METHOD_TS_18661_3__
+    #define __FLT_EVAL_METHOD_TS_18661_3__ 2
+    #undef __unix
+    #define __unix 1
+    #undef __UINT32_MAX__
+    #define __UINT32_MAX__ 0xffffffffU
+    #undef __DBL_DENORM_MIN__
+    #define __DBL_DENORM_MIN__ ((double)4.94065645841246544176568792868221372e-324L)
+    #undef __FLT128_MIN_EXP__
+    #define __FLT128_MIN_EXP__ (-16381)
+    #undef __WINT_MIN__
+    #define __WINT_MIN__ 0U
+    #undef __FLT128_MIN_10_EXP__
+    #define __FLT128_MIN_10_EXP__ (-4931)
+    #undef __FLT32X_IS_IEC_60559__
+    #define __FLT32X_IS_IEC_60559__ 2
+    #undef __INT_LEAST16_WIDTH__
+    #define __INT_LEAST16_WIDTH__ 16
+    #undef __SCHAR_MAX__
+    #define __SCHAR_MAX__ 0x7f
+    #undef __FLT128_MANT_DIG__
+    #define __FLT128_MANT_DIG__ 113
+    #undef __WCHAR_MIN__
+    #define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
+    #undef __INT64_C
+    #define __INT64_C(c) c ## LL
+    #undef __FLT32X_MANT_DIG__
+    #define __FLT32X_MANT_DIG__ 53
+    #undef __FLT64X_EPSILON__
+    #define __FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x
+    #undef __DEC64_MIN_EXP__
+    #define __DEC64_MIN_EXP__ (-382)
+    #undef __DBL_DIG__
+    #define __DBL_DIG__ 15
+    #undef __FLT32_DIG__
+    #define __FLT32_DIG__ 6
+    #undef __FLT_EPSILON__
+    #define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F
+    #undef __SHRT_WIDTH__
+    #define __SHRT_WIDTH__ 16
+    #undef __FLT32_IS_IEC_60559__
+    #define __FLT32_IS_IEC_60559__ 2
+    #undef __LDBL_MIN__
+    #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
+    #undef __DBL_IS_IEC_60559__
+    #define __DBL_IS_IEC_60559__ 2
+    #undef __DEC32_MAX__
+    #define __DEC32_MAX__ 9.999999E96DF
+    #undef __FLT64X_DENORM_MIN__
+    #define __FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x
+    #undef __FLT32X_HAS_INFINITY__
+    #define __FLT32X_HAS_INFINITY__ 1
+    #undef __INT32_MAX__
+    #define __INT32_MAX__ 0x7fffffff
+    #undef __FLT16_DIG__
+    #define __FLT16_DIG__ 3
+    #undef __unix__
+    #define __unix__ 1
+    #undef __INT_WIDTH__
+    #define __INT_WIDTH__ 16
+    #undef __SIZEOF_LONG__
+    #define __SIZEOF_LONG__ 4
+    #undef __UINT16_C
+    #define __UINT16_C(c) c
+    #undef __DECIMAL_DIG__
+    #define __DECIMAL_DIG__ 21
+    #undef __FLT64_EPSILON__
+    #define __FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64
+    #undef __gnu_linux__
+    #define __gnu_linux__ 1
+    #undef __FLT128_IS_IEC_60559__
+    #define __FLT128_IS_IEC_60559__ 2
+    #undef __FLT64X_MIN_10_EXP__
+    #define __FLT64X_MIN_10_EXP__ (-4931)
+    #undef __LDBL_HAS_QUIET_NAN__
+    #define __LDBL_HAS_QUIET_NAN__ 1
+    #undef __FLT16_MIN_EXP__
+    #define __FLT16_MIN_EXP__ (-13)
+    #undef __FLT64_MANT_DIG__
+    #define __FLT64_MANT_DIG__ 53
+    #undef __FLT64X_MANT_DIG__
+    #define __FLT64X_MANT_DIG__ 64
+    #undef __GNUC__
+    #define __GNUC__ 12
+    #undef __pie__
+    #define __pie__ 2
+    #undef __MMX__
+    #define __MMX__ 1
+    #undef __FLT_HAS_DENORM__
+    #define __FLT_HAS_DENORM__ 1
+    #undef __SIZEOF_LONG_DOUBLE__
+    #define __SIZEOF_LONG_DOUBLE__ 12
+    #undef __BIGGEST_ALIGNMENT__
+    #define __BIGGEST_ALIGNMENT__ 16
+    #undef __FLT64_MAX_10_EXP__
+    #define __FLT64_MAX_10_EXP__ 308
+    #undef __FLT16_MAX_10_EXP__
+    #define __FLT16_MAX_10_EXP__ 4
+    #undef __DBL_MAX__
+    #define __DBL_MAX__ ((double)1.79769313486231570814527423731704357e+308L)
+    #undef __INT_FAST32_MAX__
+    #define __INT_FAST32_MAX__ 0x7fffffff
+    #undef __DBL_HAS_INFINITY__
+    #define __DBL_HAS_INFINITY__ 1
+    #undef __SIZEOF_FLOAT__
+    #define __SIZEOF_FLOAT__ 4
+    #undef __HAVE_SPECULATION_SAFE_VALUE
+    #define __HAVE_SPECULATION_SAFE_VALUE 1
+    #undef __DEC32_MIN_EXP__
+    #define __DEC32_MIN_EXP__ (-94)
+    #undef __INTPTR_WIDTH__
+    #define __INTPTR_WIDTH__ 32
+    #undef __FLT64X_HAS_INFINITY__
+    #define __FLT64X_HAS_INFINITY__ 1
+    #undef __UINT_LEAST32_MAX__
+    #define __UINT_LEAST32_MAX__ 0xffffffffU
+    #undef __FLT32X_HAS_DENORM__
+    #define __FLT32X_HAS_DENORM__ 1
+    #undef __INT_FAST16_TYPE__
+    #define __INT_FAST16_TYPE__ int
+    #undef __LDBL_HAS_DENORM__
+    #define __LDBL_HAS_DENORM__ 1
+    #undef __SEG_GS
+    #define __SEG_GS 1
+    #undef __FLT128_HAS_INFINITY__
+    #define __FLT128_HAS_INFINITY__ 1
+    #undef __DEC32_MIN__
+    #define __DEC32_MIN__ 1E-95DF
+    #undef __DBL_MAX_EXP__
+    #define __DBL_MAX_EXP__ 1024
+    #undef __WCHAR_WIDTH__
+    #define __WCHAR_WIDTH__ 16
+    #undef __FLT32_MAX__
+    #define __FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32
+    #undef __DEC128_EPSILON__
+    #define __DEC128_EPSILON__ 1E-33DL
+    #undef __FLT16_DECIMAL_DIG__
+    #define __FLT16_DECIMAL_DIG__ 5
+    #undef __ATOMIC_HLE_RELEASE
+    #define __ATOMIC_HLE_RELEASE 131072
+    #undef __PTRDIFF_MAX__
+    #define __PTRDIFF_MAX__ 0x7fffffff
+    #undef __ATOMIC_HLE_ACQUIRE
+    #define __ATOMIC_HLE_ACQUIRE 65536
+    #undef __LONG_LONG_MAX__
+    #define __LONG_LONG_MAX__ 0x7fffffffffffffffLL
+    #undef __SIZEOF_SIZE_T__
+    #define __SIZEOF_SIZE_T__ 2
+    #undef __FLT64X_MIN_EXP__
+    #define __FLT64X_MIN_EXP__ (-16381)
+    #undef __SIZEOF_WINT_T__
+    #define __SIZEOF_WINT_T__ 4
+    #undef __LONG_LONG_WIDTH__
+    #define __LONG_LONG_WIDTH__ 64
+    #undef __FLT32_MAX_EXP__
+    #define __FLT32_MAX_EXP__ 128
+    #undef __GXX_ABI_VERSION
+    #define __GXX_ABI_VERSION 1017
+    #undef __FLT_MIN_EXP__
+    #define __FLT_MIN_EXP__ (-125)
+    #undef __INT16_MAX__
+    #define __INT16_MAX__ 0x7fff
+    #undef __INT_FAST64_TYPE__
+    #define __INT_FAST64_TYPE__ long long int
+    #undef __FLT64_DENORM_MIN__
+    #define __FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64
+    #undef __DBL_MIN__
+    #define __DBL_MIN__ ((double)2.22507385850720138309023271733240406e-308L)
+    #undef __FLT16_DENORM_MIN__
+    #define __FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16
+    #undef __FLT128_EPSILON__
+    #define __FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128
+    #undef __FLT64X_NORM_MAX__
+    #define __FLT64X_NORM_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+    #undef __SIZEOF_POINTER__
+    #define __SIZEOF_POINTER__ 4
+    #undef __DBL_HAS_QUIET_NAN__
+    #define __DBL_HAS_QUIET_NAN__ 1
+    #undef __FLT32X_EPSILON__
+    #define __FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x
+    #undef __DECIMAL_BID_FORMAT__
+    #define __DECIMAL_BID_FORMAT__ 1
+    #undef __FLT64_MIN_EXP__
+    #define __FLT64_MIN_EXP__ (-1021)
+    #undef __FLT64_MIN_10_EXP__
+    #define __FLT64_MIN_10_EXP__ (-307)
+    #undef __FLT16_MIN_10_EXP__
+    #define __FLT16_MIN_10_EXP__ (-4)
+    #undef __FLT64X_DECIMAL_DIG__
+    #define __FLT64X_DECIMAL_DIG__ 21
+    #undef __DEC128_MIN__
+    #define __DEC128_MIN__ 1E-6143DL
+    #undef __REGISTER_PREFIX__
+    #define __REGISTER_PREFIX__
+    #undef __UINT16_MAX__
+    #define __UINT16_MAX__ 0xffff
+    #undef __DBL_HAS_DENORM__
+    #define __DBL_HAS_DENORM__ 1
+    #undef __LDBL_HAS_INFINITY__
+    #define __LDBL_HAS_INFINITY__ 1
+    #undef __FLT32_MIN__
+    #define __FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32
+    #undef __UINT8_TYPE__
+    #define __UINT8_TYPE__ unsigned char
+    #undef __FLT_DIG__
+    #define __FLT_DIG__ 6
+    #undef __NO_INLINE__
+    #define __NO_INLINE__ 1
+    #undef __DEC_EVAL_METHOD__
+    #define __DEC_EVAL_METHOD__ 2
+    #undef __DEC128_MAX__
+    #define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
+    #undef __i386
+    #define __i386 1
+    #undef __FLT_MANT_DIG__
+    #define __FLT_MANT_DIG__ 24
+    #undef __LDBL_DECIMAL_DIG__
+    #define __LDBL_DECIMAL_DIG__ 21
+    #undef __VERSION__
+    #define __VERSION__ "12.2.1 20230201"
+    #undef __UINT64_C
+    #define __UINT64_C(c) c ## ULL
+    #undef _STDC_PREDEF_H
+    #define _STDC_PREDEF_H 1
+    #undef __INT_LEAST32_MAX__
+    #define __INT_LEAST32_MAX__ 0x7fffffff
+    #undef __FLT128_MAX_EXP__
+    #define __FLT128_MAX_EXP__ 16384
+    #undef __FLT32_MANT_DIG__
+    #define __FLT32_MANT_DIG__ 24
+    #undef __FLOAT_WORD_ORDER__
+    #define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
+    #undef __FLT32X_MIN_EXP__
+    #define __FLT32X_MIN_EXP__ (-1021)
+    #undef i386
+    #define i386 1
+    #undef __FLT128_HAS_DENORM__
+    #define __FLT128_HAS_DENORM__ 1
+    #undef __FLT32_DECIMAL_DIG__
+    #define __FLT32_DECIMAL_DIG__ 9
+    #undef __FLT128_DIG__
+    #define __FLT128_DIG__ 33
+    #undef __INT32_C
+    #define __INT32_C(c) c ## L
+    #undef __DEC64_EPSILON__
+    #define __DEC64_EPSILON__ 1E-15DD
+    #undef __ORDER_PDP_ENDIAN__
+    #define __ORDER_PDP_ENDIAN__ 3412
+    #undef __DEC128_MIN_EXP__
+    #define __DEC128_MIN_EXP__ (-6142)
+    #undef __code_model_32__
+    #define __code_model_32__ 1
+    #undef __INT_FAST32_TYPE__
+    #define __INT_FAST32_TYPE__ long
+    #undef __UINT_LEAST16_TYPE__
+    #define __UINT_LEAST16_TYPE__ short unsigned int
+    #undef unix
+    #define unix 1
+    #undef __i386__
+    #define __i386__ 1
+    #undef __SIZE_TYPE__
+    #define __SIZE_TYPE__ unsigned int
+    #undef __UINT64_MAX__
+    #define __UINT64_MAX__ 0xffffffffffffffffULL
+    #undef __FLT_IS_IEC_60559__
+    #define __FLT_IS_IEC_60559__ 2
+    #undef __GNUC_WIDE_EXECUTION_CHARSET_NAME
+    #define __GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE"
+    #undef __FLT64X_DIG__
+    #define __FLT64X_DIG__ 18
+    #undef __INT8_TYPE__
+    #define __INT8_TYPE__ signed char
+    #undef __ELF__
+    #define __ELF__ 1
+    #undef __UINT32_TYPE__
+    #define __UINT32_TYPE__ unsigned long
+    #undef __FLT_RADIX__
+    #define __FLT_RADIX__ 2
+    #undef __INT_LEAST16_TYPE__
+    #define __INT_LEAST16_TYPE__ short int
+    #undef __LDBL_EPSILON__
+    #define __LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L
+    #undef __UINTMAX_C
+    #define __UINTMAX_C(c) c ## ULL
+    #undef __k8
+    #define __k8 1
+    #undef __FLT32X_MIN__
+    #define __FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x
+    #undef __SIG_ATOMIC_MAX__
+    #define __SIG_ATOMIC_MAX__ 0x7fffffff
+    #undef __USER_LABEL_PREFIX__
+    #define __USER_LABEL_PREFIX__
+    #undef __SIZEOF_PTRDIFF_T__
+    #define __SIZEOF_PTRDIFF_T__ 4
+    #undef __LDBL_DIG__
+    #define __LDBL_DIG__ 18
+    #undef __FLT64_IS_IEC_60559__
+    #define __FLT64_IS_IEC_60559__ 2
+    #undef __FLT16_IS_IEC_60559__
+    #define __FLT16_IS_IEC_60559__ 2
+    #undef __FLT16_MAX_EXP__
+    #define __FLT16_MAX_EXP__ 16
+    #undef __DEC32_SUBNORMAL_MIN__
+    #define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
+    #undef __INT_FAST16_MAX__
+    #define __INT_FAST16_MAX__ 0x7fffffff
+    #undef __FLT64_DIG__
+    #define __FLT64_DIG__ 15
+    #undef __UINT_FAST32_MAX__
+    #define __UINT_FAST32_MAX__ 0xffffffffU
+    #undef __UINT_LEAST64_TYPE__
+    #define __UINT_LEAST64_TYPE__ long long unsigned int
+    #undef __FLT16_EPSILON__
+    #define __FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16
+    #undef __ILP32__
+    #define __ILP32__ 1
+    #undef __FLT_HAS_QUIET_NAN__
+    #define __FLT_HAS_QUIET_NAN__ 1
+    #undef __FLT_MAX_10_EXP__
+    #define __FLT_MAX_10_EXP__ 38
+    #undef __LONG_MAX__
+    #define __LONG_MAX__ 0x7fffffffL
+    #undef __FLT64X_HAS_DENORM__
+    #define __FLT64X_HAS_DENORM__ 1
+    #undef __DEC128_SUBNORMAL_MIN__
+    #define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
+    #undef __FLT_HAS_INFINITY__
+    #define __FLT_HAS_INFINITY__ 1
+    #undef __GNUC_EXECUTION_CHARSET_NAME
+    #define __GNUC_EXECUTION_CHARSET_NAME "UTF-8"
+    #undef _ILP32
+    #define _ILP32 1
+    #undef __UINT_FAST16_TYPE__
+    #define __UINT_FAST16_TYPE__ unsigned int
+    #undef __DEC64_MAX__
+    #define __DEC64_MAX__ 9.999999999999999E384DD
+    #undef __INT_FAST32_WIDTH__
+    #define __INT_FAST32_WIDTH__ 32
+    #undef __CHAR16_TYPE__
+    #define __CHAR16_TYPE__ short unsigned int
+    #undef __PRAGMA_REDEFINE_EXTNAME
+    #define __PRAGMA_REDEFINE_EXTNAME 1
+    #undef __SIZE_WIDTH__
+    #define __SIZE_WIDTH__ 32
+    #undef __SEG_FS
+    #define __SEG_FS 1
+    #undef __INT_LEAST16_MAX__
+    #define __INT_LEAST16_MAX__ 0x7fff
+    #undef __FLT16_NORM_MAX__
+    #define __FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16
+    #undef __DEC64_MANT_DIG__
+    #define __DEC64_MANT_DIG__ 16
+    #undef __INT64_MAX__
+    #define __INT64_MAX__ 0x7fffffffffffffffLL
+    #undef __FLT32_DENORM_MIN__
+    #define __FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32
+    #undef __SIG_ATOMIC_WIDTH__
+    #define __SIG_ATOMIC_WIDTH__ 32
+    #undef __INT_LEAST64_TYPE__
+    #define __INT_LEAST64_TYPE__ long long int
+    #undef __INT16_TYPE__
+    #define __INT16_TYPE__ short int
+    #undef __INT_LEAST8_TYPE__
+    #define __INT_LEAST8_TYPE__ signed char
+    #undef __FLT16_MAX__
+    #define __FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16
+    #undef __SIZEOF_INT__
+    #define __SIZEOF_INT__ 4
+    #undef __DEC32_MAX_EXP__
+    #define __DEC32_MAX_EXP__ 97
+    #undef __INT_FAST8_MAX__
+    #define __INT_FAST8_MAX__ 0x7f
+    #undef __FLT128_MAX__
+    #define __FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128
+    #undef __INTPTR_MAX__
+    #define __INTPTR_MAX__ 0x7fffffff
+    #undef linux
+    #define linux 1
+    #undef __FLT64_HAS_QUIET_NAN__
+    #define __FLT64_HAS_QUIET_NAN__ 1
+    #undef __FLT32_MIN_10_EXP__
+    #define __FLT32_MIN_10_EXP__ (-37)
+    #undef __FLT32X_DIG__
+    #define __FLT32X_DIG__ 15
+    #undef __PTRDIFF_WIDTH__
+    #define __PTRDIFF_WIDTH__ 16
+    #undef __LDBL_MANT_DIG__
+    #define __LDBL_MANT_DIG__ 64
+    #undef __FLT64_HAS_INFINITY__
+    #define __FLT64_HAS_INFINITY__ 1
+    #undef __FLT64X_MAX__
+    #define __FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+    #undef __FLT16_HAS_INFINITY__
+    #define __FLT16_HAS_INFINITY__ 1
+    #undef __SIG_ATOMIC_MIN__
+    #define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
+    #undef __DEC32_MANT_DIG__
+    #define __DEC32_MANT_DIG__ 7
+    #undef __FLT16_MANT_DIG__
+    #define __FLT16_MANT_DIG__ 11
+    #undef __k8__
+    #define __k8__ 1
+    #undef __INTPTR_TYPE__
+    #define __INTPTR_TYPE__ long
+    #undef __UINT16_TYPE__
+    #define __UINT16_TYPE__ short unsigned int
+    #undef __WCHAR_TYPE__
+    #define __WCHAR_TYPE__ int
+    #undef __pic__
+    #define __pic__ 2
+    #undef __UINTPTR_MAX__
+    #define __UINTPTR_MAX__ 0xffffffffU
+    #undef __INT_FAST64_WIDTH__
+    #define __INT_FAST64_WIDTH__ 64
+    #undef __INT_FAST64_MAX__
+    #define __INT_FAST64_MAX__ 0x7fffffffffffffffLL
+    #undef __FLT_NORM_MAX__
+    #define __FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F
+    #undef __FLT32_HAS_INFINITY__
+    #define __FLT32_HAS_INFINITY__ 1
+    #undef __FLT64X_MAX_EXP__
+    #define __FLT64X_MAX_EXP__ 16384
+    #undef __UINT_FAST64_TYPE__
+    #define __UINT_FAST64_TYPE__ long long unsigned int
+    #undef __INT_MAX__
+    #define __INT_MAX__ 0x7fff
+    #undef __linux__
+    #define __linux__ 1
+    #undef __INT64_TYPE__
+    #define __INT64_TYPE__ long long int
+    #undef __FLT_MAX_EXP__
+    #define __FLT_MAX_EXP__ 128
+    #undef __DBL_MANT_DIG__
+    #define __DBL_MANT_DIG__ 53
+    #undef __SIZEOF_FLOAT128__
+    #define __SIZEOF_FLOAT128__ 16
+    #undef __INT_LEAST64_MAX__
+    #define __INT_LEAST64_MAX__ 0x7fffffffffffffffLL
+    #undef __DEC64_MIN__
+    #define __DEC64_MIN__ 1E-383DD
+    #undef __WINT_TYPE__
+    #define __WINT_TYPE__ unsigned long
+    #undef __UINT_LEAST32_TYPE__
+    #define __UINT_LEAST32_TYPE__ unsigned long
+    #undef __SIZEOF_SHORT__
+    #define __SIZEOF_SHORT__ 2
+    #undef __FLT32_NORM_MAX__
+    #define __FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32
+    #undef __SSE__
+    #define __SSE__ 1
+    #undef __LDBL_MIN_EXP__
+    #define __LDBL_MIN_EXP__ (-16381)
+    #undef __FLT64_MAX__
+    #define __FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64
+    #undef __WINT_WIDTH__
+    #define __WINT_WIDTH__ 32
+    #undef __INT_LEAST8_MAX__
+    #define __INT_LEAST8_MAX__ 0x7f
+    #undef __INT_LEAST64_WIDTH__
+    #define __INT_LEAST64_WIDTH__ 64
+    #undef __LDBL_MAX_EXP__
+    #define __LDBL_MAX_EXP__ 16384
+    #undef __FLT32X_MAX_10_EXP__
+    #define __FLT32X_MAX_10_EXP__ 308
+    #undef __FLT16_MIN__
+    #define __FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16
+    #undef __FLT64X_IS_IEC_60559__
+    #define __FLT64X_IS_IEC_60559__ 2
+    #undef __LDBL_MAX_10_EXP__
+    #define __LDBL_MAX_10_EXP__ 4932
+    #undef __ATOMIC_RELAXED
+    #define __ATOMIC_RELAXED 0
+    #undef __DBL_EPSILON__
+    #define __DBL_EPSILON__ ((double)2.22044604925031308084726333618164062e-16L)
+    #undef __FLT128_MIN__
+    #define __FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128
+    #undef __UINT8_C
+    #define __UINT8_C(c) c
+    #undef __FLT64_MAX_EXP__
+    #define __FLT64_MAX_EXP__ 1024
+    #undef __INT_LEAST32_TYPE__
+    #define __INT_LEAST32_TYPE__ long
+    #undef __SIZEOF_WCHAR_T__
+    #define __SIZEOF_WCHAR_T__ 2
+    #undef __UINT64_TYPE__
+    #define __UINT64_TYPE__ long long unsigned int
+    #undef __GNUC_PATCHLEVEL__
+    #define __GNUC_PATCHLEVEL__ 1
+    #undef __FLT128_NORM_MAX__
+    #define __FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128
+    #undef __FLT64_NORM_MAX__
+    #define __FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64
+    #undef __FLT128_HAS_QUIET_NAN__
+    #define __FLT128_HAS_QUIET_NAN__ 1
+    #undef __INTMAX_MAX__
+    #define __INTMAX_MAX__ 0x7fffffffffffffffLL
+    #undef __INT_FAST8_TYPE__
+    #define __INT_FAST8_TYPE__ signed char
+    #undef __FLT64X_MIN__
+    #define __FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x
+    #undef __GNUC_STDC_INLINE__
+    #define __GNUC_STDC_INLINE__ 1
+    #undef __FLT64_HAS_DENORM__
+    #define __FLT64_HAS_DENORM__ 1
+    #undef __FLT32_EPSILON__
+    #define __FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32
+    #undef __FLT16_HAS_DENORM__
+    #define __FLT16_HAS_DENORM__ 1
+    #undef __DBL_DECIMAL_DIG__
+    #define __DBL_DECIMAL_DIG__ 17
+    #undef __INT_FAST8_WIDTH__
+    #define __INT_FAST8_WIDTH__ 8
+    #undef __FXSR__
+    #define __FXSR__ 1
+    #undef __FLT32X_MAX__
+    #define __FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x
+    #undef __DBL_NORM_MAX__
+    #define __DBL_NORM_MAX__ ((double)1.79769313486231570814527423731704357e+308L)
+    #undef __BYTE_ORDER__
+    #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+    #undef __INTMAX_WIDTH__
+    #define __INTMAX_WIDTH__ 64
+    #undef __ORDER_BIG_ENDIAN__
+    #define __ORDER_BIG_ENDIAN__ 4321
+    #undef __UINT32_C
+    #define __UINT32_C(c) c ## UL
+    #undef __FLT_DENORM_MIN__
+    #define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F
+    #undef __INT8_MAX__
+    #define __INT8_MAX__ 0x7f
+    #undef __LONG_WIDTH__
+    #define __LONG_WIDTH__ 32
+    #undef __PIC__
+    #define __PIC__ 2
+    #undef __UINT_FAST32_TYPE__
+    #define __UINT_FAST32_TYPE__ unsigned long
+    #undef __FLT32X_NORM_MAX__
+    #define __FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x
+    #undef __CHAR32_TYPE__
+    #define __CHAR32_TYPE__ unsigned long
+    #undef __FLT_MAX__
+    #define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F
+    #undef __SSE2__
+    #define __SSE2__ 1
+    #undef __INT32_TYPE__
+    #define __INT32_TYPE__ long
+    #undef __SIZEOF_DOUBLE__
+    #define __SIZEOF_DOUBLE__ 8
+    #undef __FLT_MIN_10_EXP__
+    #define __FLT_MIN_10_EXP__ (-37)
+    #undef __FLT64_MIN__
+    #define __FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64
+    #undef __INT_LEAST32_WIDTH__
+    #define __INT_LEAST32_WIDTH__ 32
+    #undef __INTMAX_TYPE__
+    #define __INTMAX_TYPE__ long long int
+    #undef __DEC128_MAX_EXP__
+    #define __DEC128_MAX_EXP__ 6145
+    #undef __FLT32X_HAS_QUIET_NAN__
+    #define __FLT32X_HAS_QUIET_NAN__ 1
+    #undef __ATOMIC_CONSUME
+    #define __ATOMIC_CONSUME 1
+    #undef __GNUC_MINOR__
+    #define __GNUC_MINOR__ 2
+    #undef __INT_FAST16_WIDTH__
+    #define __INT_FAST16_WIDTH__ 32
+    #undef __UINTMAX_MAX__
+    #define __UINTMAX_MAX__ 0xffffffffffffffffULL
+    #undef __PIE__
+    #define __PIE__ 2
+    #undef __FLT32X_DENORM_MIN__
+    #define __FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x
+    #undef __DBL_MAX_10_EXP__
+    #define __DBL_MAX_10_EXP__ 308
+    #undef __LDBL_DENORM_MIN__
+    #define __LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L
+    #undef __INT16_C
+    #define __INT16_C(c) c
+    #undef __PTRDIFF_TYPE__
+    #define __PTRDIFF_TYPE__ int
+    #undef __ATOMIC_SEQ_CST
+    #define __ATOMIC_SEQ_CST 5
+    #undef __FLT32X_MIN_10_EXP__
+    #define __FLT32X_MIN_10_EXP__ (-307)
+    #undef __UINTPTR_TYPE__
+    #define __UINTPTR_TYPE__ unsigned int
+    #undef __DEC64_SUBNORMAL_MIN__
+    #define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
+    #undef __DEC128_MANT_DIG__
+    #define __DEC128_MANT_DIG__ 34
+    #undef __LDBL_MIN_10_EXP__
+    #define __LDBL_MIN_10_EXP__ (-4931)
+    #undef __SIZEOF_LONG_LONG__
+    #define __SIZEOF_LONG_LONG__ 8
+    #undef __FLT128_DECIMAL_DIG__
+    #define __FLT128_DECIMAL_DIG__ 36
+    #undef __FLT32_HAS_QUIET_NAN__
+    #define __FLT32_HAS_QUIET_NAN__ 1
+    #undef __FLT_DECIMAL_DIG__
+    #define __FLT_DECIMAL_DIG__ 9
+    #undef __UINT_FAST16_MAX__
+    #define __UINT_FAST16_MAX__ 0xffffU
+    #undef __LDBL_NORM_MAX__
+    #define __LDBL_NORM_MAX__ 1.18973149535723176502126385303097021e+4932L
+    #undef __UINT_FAST8_TYPE__
+    #define __UINT_FAST8_TYPE__ unsigned char
+    #undef __ATOMIC_ACQ_REL
+    #define __ATOMIC_ACQ_REL 4
+    #undef __ATOMIC_RELEASE
+    #define __ATOMIC_RELEASE 3
+
+errno:
+    e2big: '7'
+    eacces: '13'
+    eaddrinuse: '98'
+    eaddrnotavail: '99'
+    eafnosupport: '97'
+    eagain: '11'
+    ealready: '114'
+    ebade: '52'
+    ebadf: '9'
+    ebadfd: '77'
+    ebadmsg: '74'
+    ebadr: '53'
+    ebadrqc: '56'
+    ebadslt: '57'
+    ebusy: '16'
+    ecanceled: '125'
+    echild: '10'
+    echrng: '44'
+    ecomm: '70'
+    econnaborted: '103'
+    econnrefused: '111'
+    econnreset: '104'
+    edeadlk: '35'
+    edeadlock: '35'
+    edestaddrreq: '89'
+    edom: '33'
+    edquot: '122'
+    eexist: '17'
+    efault: '14'
+    efbig: '27'
+    ehostdown: '112'
+    ehostunreach: '113'
+    eidrm: '43'
+    eilseq: '84'
+    einprogress: '115'
+    eintr: '4'
+    einval: '22'
+    eio: '5'
+    eisconn: '106'
+    eisdir: '21'
+    eisnam: '120'
+    ekeyexpired: '127'
+    ekeyrejected: '129'
+    ekeyrevoked: '128'
+    el2hlt: '51'
+    el2nsync: '45'
+    el3hlt: '46'
+    el3rst: '47'
+    elibacc: '79'
+    elibbad: '80'
+    elibexec: '83'
+    elibmax: '82'
+    elibscn: '81'
+    eloop: '40'
+    emediumtype: '124'
+    emfile: '24'
+    emlink: '31'
+    emsgsize: '90'
+    emultihop: '72'
+    enametoolong: '36'
+    enetdown: '100'
+    enetreset: '102'
+    enetunreach: '101'
+    enfile: '23'
+    enobufs: '105'
+    enodata: '61'
+    enodev: '19'
+    enoent: '2'
+    enoexec: '8'
+    enokey: '126'
+    enolck: '37'
+    enolink: '67'
+    enomedium: '123'
+    enomem: '12'
+    enomsg: '42'
+    enonet: '64'
+    enopkg: '65'
+    enoprotoopt: '92'
+    enospc: '28'
+    enosr: '63'
+    enostr: '60'
+    enosys: '38'
+    enotblk: '15'
+    enotconn: '107'
+    enotdir: '20'
+    enotempty: '39'
+    enotrecoverable: '131'
+    enotsock: '88'
+    enotsup: '95'
+    enotty: '25'
+    enotuniq: '76'
+    enxio: '6'
+    eopnotsupp: '95'
+    eoverflow: '75'
+    eownerdead: '130'
+    eperm: '1'
+    epfnosupport: '96'
+    epipe: '32'
+    eproto: '71'
+    eprotonosupport: '93'
+    eprototype: '91'
+    erange: '34'
+    eremchg: '78'
+    eremote: '66'
+    eremoteio: '121'
+    erestart: '85'
+    erofs: '30'
+    eshutdown: '108'
+    esocktnosupport: '94'
+    espipe: '29'
+    esrch: '3'
+    estale: '116'
+    estrpipe: '86'
+    etime: '62'
+    etimedout: '110'
+    etxtbsy: '26'
+    euclean: '117'
+    eunatch: '49'
+    eusers: '87'
+    ewouldblock: '11'
+    exdev: '18'
+    exfull: '54'
+has__builtin_va_list: true
+int_fast8_t: signed char
+int_fast16_t: signed int
+int_fast32_t: long
+int_fast64_t: long long
+intptr_t: long
+little_endian: true
+nsig: '65'
+ptrdiff_t: int
+sig_atomic_t: int
+size_t: unsigned int
+sizeof_double: 8
+sizeof_float: 4
+sizeof_fun: -1
+sizeof_int: 2
+sizeof_long: 4
+sizeof_longdouble: 16
+sizeof_longlong: 8
+sizeof_ptr: 4
+sizeof_short: 2
+sizeof_void: -1
+ssize_t: int
+time_t: long
+uint_fast8_t: unsigned char
+uint_fast16_t: unsigned int
+uint_fast32_t: unsigned long
+uint_fast64_t: unsigned long long
+uintptr_t: unsigned long
+version: none
+wchar_t: int
+weof: (0xffffffffUL)
+wint_t: unsigned long
+wordsize: '16'
+posix_version: '200809L'
+bufsiz: '8192'
+eof: '(-1)'
+fopen_max: '16'
+filename_max: '2048'
+path_max: '256'
+host_name_max: '64'
+tty_name_max: '32'
+l_tmpnam: '2048'
+tmp_max: '0xFFFFFFFF'
+rand_max: '32767'
+mb_cur_max: '((size_t)16)'
+machdep_name: machdep_x86_16
diff --git a/share/machdeps/machdep_x86_32.yaml b/share/machdeps/machdep_x86_32.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..255029b4cc32a97a4d801fde4c0d7bb7c897b70b
--- /dev/null
+++ b/share/machdeps/machdep_x86_32.yaml
@@ -0,0 +1,915 @@
+alignof_aligned: 16
+alignof_double: 4
+alignof_float: 4
+alignof_fun: -1
+alignof_int: 4
+alignof_long: 4
+alignof_longdouble: 4
+alignof_longlong: 4
+alignof_ptr: 4
+alignof_short: 2
+alignof_str: 1
+bufsiz: '8192'
+char_is_unsigned: false
+compiler: generic
+cpp_arch_flags:
+- -m32
+custom_defs: |
+    #undef __DBL_MIN_EXP__
+    #define __DBL_MIN_EXP__ (-1021)
+    #undef __UINT_LEAST16_MAX__
+    #define __UINT_LEAST16_MAX__ 0xffff
+    #undef __FLT16_HAS_QUIET_NAN__
+    #define __FLT16_HAS_QUIET_NAN__ 1
+    #undef __ATOMIC_ACQUIRE
+    #define __ATOMIC_ACQUIRE 2
+    #undef __FLT128_MAX_10_EXP__
+    #define __FLT128_MAX_10_EXP__ 4932
+    #undef __FLT_MIN__
+    #define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F
+    #undef __UINT_LEAST8_TYPE__
+    #define __UINT_LEAST8_TYPE__ unsigned char
+    #undef __SIZEOF_FLOAT80__
+    #define __SIZEOF_FLOAT80__ 12
+    #undef __BFLT16_DENORM_MIN__
+    #define __BFLT16_DENORM_MIN__ 9.18354961579912115600575419704879436e-41BF16
+    #undef __INTMAX_C
+    #define __INTMAX_C(c) c ## LL
+    #undef __CHAR_BIT__
+    #define __CHAR_BIT__ 8
+    #undef __UINT8_MAX__
+    #define __UINT8_MAX__ 0xff
+    #undef __SCHAR_WIDTH__
+    #define __SCHAR_WIDTH__ 8
+    #undef __WINT_MAX__
+    #define __WINT_MAX__ 0xffffffffU
+    #undef __FLT32_MIN_EXP__
+    #define __FLT32_MIN_EXP__ (-125)
+    #undef __BFLT16_NORM_MAX__
+    #define __BFLT16_NORM_MAX__ 3.38953138925153547590470800371487867e+38BF16
+    #undef __BFLT16_MIN_10_EXP__
+    #define __BFLT16_MIN_10_EXP__ (-37)
+    #undef __ORDER_LITTLE_ENDIAN__
+    #define __ORDER_LITTLE_ENDIAN__ 1234
+    #undef __WCHAR_MAX__
+    #define __WCHAR_MAX__ 0x7fffffffL
+    #undef __FLT32X_DECIMAL_DIG__
+    #define __FLT32X_DECIMAL_DIG__ 17
+    #undef __FLT_EVAL_METHOD__
+    #define __FLT_EVAL_METHOD__ 2
+    #undef __FLT64_DECIMAL_DIG__
+    #define __FLT64_DECIMAL_DIG__ 17
+    #undef __UINT_FAST64_MAX__
+    #define __UINT_FAST64_MAX__ 0xffffffffffffffffULL
+    #undef __SIG_ATOMIC_TYPE__
+    #define __SIG_ATOMIC_TYPE__ int
+    #undef __DBL_MIN_10_EXP__
+    #define __DBL_MIN_10_EXP__ (-307)
+    #undef __FINITE_MATH_ONLY__
+    #define __FINITE_MATH_ONLY__ 0
+    #undef __FLT32X_MAX_EXP__
+    #define __FLT32X_MAX_EXP__ 1024
+    #undef __FLT32_HAS_DENORM__
+    #define __FLT32_HAS_DENORM__ 1
+    #undef __UINT_FAST8_MAX__
+    #define __UINT_FAST8_MAX__ 0xff
+    #undef __FLT32_MAX_10_EXP__
+    #define __FLT32_MAX_10_EXP__ 38
+    #undef __DEC64_MAX_EXP__
+    #define __DEC64_MAX_EXP__ 385
+    #undef __INT8_C
+    #define __INT8_C(c) c
+    #undef __INT_LEAST8_WIDTH__
+    #define __INT_LEAST8_WIDTH__ 8
+    #undef __UINT_LEAST64_MAX__
+    #define __UINT_LEAST64_MAX__ 0xffffffffffffffffULL
+    #undef __SHRT_MAX__
+    #define __SHRT_MAX__ 0x7fff
+    #undef __LDBL_MAX__
+    #define __LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L
+    #undef __FLT64X_MAX_10_EXP__
+    #define __FLT64X_MAX_10_EXP__ 4932
+    #undef __BFLT16_MAX_10_EXP__
+    #define __BFLT16_MAX_10_EXP__ 38
+    #undef __BFLT16_MAX_EXP__
+    #define __BFLT16_MAX_EXP__ 128
+    #undef __LDBL_IS_IEC_60559__
+    #define __LDBL_IS_IEC_60559__ 1
+    #undef __FLT64X_HAS_QUIET_NAN__
+    #define __FLT64X_HAS_QUIET_NAN__ 1
+    #undef __UINT_LEAST8_MAX__
+    #define __UINT_LEAST8_MAX__ 0xff
+    #undef __LAHF_SAHF__
+    #define __LAHF_SAHF__ 1
+    #undef __FLT128_DENORM_MIN__
+    #define __FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128
+    #undef __UINTMAX_TYPE__
+    #define __UINTMAX_TYPE__ long long unsigned int
+    #undef __BFLT16_DECIMAL_DIG__
+    #define __BFLT16_DECIMAL_DIG__ 4
+    #undef __linux
+    #define __linux 1
+    #undef __DEC32_EPSILON__
+    #define __DEC32_EPSILON__ 1E-6DF
+    #undef __FLT_EVAL_METHOD_TS_18661_3__
+    #define __FLT_EVAL_METHOD_TS_18661_3__ 2
+    #undef __UINT32_MAX__
+    #define __UINT32_MAX__ 0xffffffffU
+    #undef __DBL_DENORM_MIN__
+    #define __DBL_DENORM_MIN__ ((double)4.94065645841246544176568792868221372e-324L)
+    #undef __FLT128_MIN_EXP__
+    #define __FLT128_MIN_EXP__ (-16381)
+    #undef __WINT_MIN__
+    #define __WINT_MIN__ 0U
+    #undef __FLT128_MIN_10_EXP__
+    #define __FLT128_MIN_10_EXP__ (-4931)
+    #undef __FLT32X_IS_IEC_60559__
+    #define __FLT32X_IS_IEC_60559__ 1
+    #undef __INT_LEAST16_WIDTH__
+    #define __INT_LEAST16_WIDTH__ 16
+    #undef __SCHAR_MAX__
+    #define __SCHAR_MAX__ 0x7f
+    #undef __FLT128_MANT_DIG__
+    #define __FLT128_MANT_DIG__ 113
+    #undef __WCHAR_MIN__
+    #define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
+    #undef __INT64_C
+    #define __INT64_C(c) c ## LL
+    #undef __SSP_STRONG__
+    #define __SSP_STRONG__ 3
+    #undef __ATOMIC_SEQ_CST
+    #define __ATOMIC_SEQ_CST 5
+    #undef __unix
+    #define __unix 1
+    #undef __INT_LEAST64_MAX__
+    #define __INT_LEAST64_MAX__ 0x7fffffffffffffffLL
+    #undef __FLT32X_MANT_DIG__
+    #define __FLT32X_MANT_DIG__ 53
+    #undef __FLT64X_EPSILON__
+    #define __FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x
+    #undef __DEC64_MIN_EXP__
+    #define __DEC64_MIN_EXP__ (-382)
+    #undef __DBL_DIG__
+    #define __DBL_DIG__ 15
+    #undef __FLT_EPSILON__
+    #define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F
+    #undef __SHRT_WIDTH__
+    #define __SHRT_WIDTH__ 16
+    #undef __FLT32_IS_IEC_60559__
+    #define __FLT32_IS_IEC_60559__ 1
+    #undef __LDBL_MIN__
+    #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
+    #undef __DBL_IS_IEC_60559__
+    #define __DBL_IS_IEC_60559__ 1
+    #undef __DEC32_MAX__
+    #define __DEC32_MAX__ 9.999999E96DF
+    #undef __FLT64X_DENORM_MIN__
+    #define __FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x
+    #undef __FLT32X_HAS_INFINITY__
+    #define __FLT32X_HAS_INFINITY__ 1
+    #undef __unix__
+    #define __unix__ 1
+    #undef __INT_WIDTH__
+    #define __INT_WIDTH__ 32
+    #undef __DECIMAL_DIG__
+    #define __DECIMAL_DIG__ 21
+    #undef __FLT64_EPSILON__
+    #define __FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64
+    #undef __gnu_linux__
+    #define __gnu_linux__ 1
+    #undef __FLT128_IS_IEC_60559__
+    #define __FLT128_IS_IEC_60559__ 1
+    #undef __FLT64X_MIN_10_EXP__
+    #define __FLT64X_MIN_10_EXP__ (-4931)
+    #undef __LDBL_HAS_QUIET_NAN__
+    #define __LDBL_HAS_QUIET_NAN__ 1
+    #undef __FLT16_MIN_EXP__
+    #define __FLT16_MIN_EXP__ (-13)
+    #undef __FLT64_MANT_DIG__
+    #define __FLT64_MANT_DIG__ 53
+    #undef __FLT64X_MANT_DIG__
+    #define __FLT64X_MANT_DIG__ 64
+    #undef __BFLT16_DIG__
+    #define __BFLT16_DIG__ 2
+    #undef __GNUC__
+    #define __GNUC__ 13
+    #undef __pie__
+    #define __pie__ 2
+    #undef __MMX__
+    #define __MMX__ 1
+    #undef __FLT_HAS_DENORM__
+    #define __FLT_HAS_DENORM__ 1
+    #undef __SIZEOF_LONG_DOUBLE__
+    #define __SIZEOF_LONG_DOUBLE__ 12
+    #undef __BIGGEST_ALIGNMENT__
+    #define __BIGGEST_ALIGNMENT__ 16
+    #undef __FLT64_MAX_10_EXP__
+    #define __FLT64_MAX_10_EXP__ 308
+    #undef __BFLT16_IS_IEC_60559__
+    #define __BFLT16_IS_IEC_60559__ 0
+    #undef __FLT16_MAX_10_EXP__
+    #define __FLT16_MAX_10_EXP__ 4
+    #undef __DBL_MAX__
+    #define __DBL_MAX__ ((double)1.79769313486231570814527423731704357e+308L)
+    #undef __INT_FAST32_MAX__
+    #define __INT_FAST32_MAX__ 0x7fffffff
+    #undef __DBL_HAS_INFINITY__
+    #define __DBL_HAS_INFINITY__ 1
+    #undef __INT64_MAX__
+    #define __INT64_MAX__ 0x7fffffffffffffffLL
+    #undef __SIZEOF_FLOAT__
+    #define __SIZEOF_FLOAT__ 4
+    #undef __HAVE_SPECULATION_SAFE_VALUE
+    #define __HAVE_SPECULATION_SAFE_VALUE 1
+    #undef __DEC32_MIN_EXP__
+    #define __DEC32_MIN_EXP__ (-94)
+    #undef __INTPTR_WIDTH__
+    #define __INTPTR_WIDTH__ 32
+    #undef __UINT_LEAST32_MAX__
+    #define __UINT_LEAST32_MAX__ 0xffffffffU
+    #undef __FLT32X_HAS_DENORM__
+    #define __FLT32X_HAS_DENORM__ 1
+    #undef __INT_FAST16_TYPE__
+    #define __INT_FAST16_TYPE__ int
+    #undef __LDBL_HAS_DENORM__
+    #define __LDBL_HAS_DENORM__ 1
+    #undef __SEG_GS
+    #define __SEG_GS 1
+    #undef __BFLT16_EPSILON__
+    #define __BFLT16_EPSILON__ 7.81250000000000000000000000000000000e-3BF16
+    #undef __FLT128_HAS_INFINITY__
+    #define __FLT128_HAS_INFINITY__ 1
+    #undef __DEC32_MIN__
+    #define __DEC32_MIN__ 1E-95DF
+    #undef __DBL_MAX_EXP__
+    #define __DBL_MAX_EXP__ 1024
+    #undef __WCHAR_WIDTH__
+    #define __WCHAR_WIDTH__ 32
+    #undef __FLT32_MAX__
+    #define __FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32
+    #undef __DEC128_EPSILON__
+    #define __DEC128_EPSILON__ 1E-33DL
+    #undef __FLT16_DECIMAL_DIG__
+    #define __FLT16_DECIMAL_DIG__ 5
+    #undef __ATOMIC_HLE_RELEASE
+    #define __ATOMIC_HLE_RELEASE 131072
+    #undef __PTRDIFF_MAX__
+    #define __PTRDIFF_MAX__ 0x7fffffff
+    #undef __ATOMIC_HLE_ACQUIRE
+    #define __ATOMIC_HLE_ACQUIRE 65536
+    #undef __LONG_LONG_MAX__
+    #define __LONG_LONG_MAX__ 0x7fffffffffffffffLL
+    #undef __SIZEOF_SIZE_T__
+    #define __SIZEOF_SIZE_T__ 4
+    #undef __BFLT16_HAS_INFINITY__
+    #define __BFLT16_HAS_INFINITY__ 1
+    #undef __FLT64X_MIN_EXP__
+    #define __FLT64X_MIN_EXP__ (-16381)
+    #undef __SIZEOF_WINT_T__
+    #define __SIZEOF_WINT_T__ 4
+    #undef __LONG_LONG_WIDTH__
+    #define __LONG_LONG_WIDTH__ 64
+    #undef __FLT32_MAX_EXP__
+    #define __FLT32_MAX_EXP__ 128
+    #undef __GXX_ABI_VERSION
+    #define __GXX_ABI_VERSION 1018
+    #undef __FLT_MIN_EXP__
+    #define __FLT_MIN_EXP__ (-125)
+    #undef __INT16_MAX__
+    #define __INT16_MAX__ 0x7fff
+    #undef __INT_FAST64_TYPE__
+    #define __INT_FAST64_TYPE__ long long int
+    #undef __BFLT16_MAX__
+    #define __BFLT16_MAX__ 3.38953138925153547590470800371487867e+38BF16
+    #undef __BFLT16_HAS_DENORM__
+    #define __BFLT16_HAS_DENORM__ 1
+    #undef __FLT64_DENORM_MIN__
+    #define __FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64
+    #undef __FLT16_DENORM_MIN__
+    #define __FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16
+    #undef __FLT128_EPSILON__
+    #define __FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128
+    #undef __FLT64X_NORM_MAX__
+    #define __FLT64X_NORM_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+    #undef __SIZEOF_POINTER__
+    #define __SIZEOF_POINTER__ 4
+    #undef __SIZE_TYPE__
+    #define __SIZE_TYPE__ unsigned int
+    #undef __DBL_HAS_QUIET_NAN__
+    #define __DBL_HAS_QUIET_NAN__ 1
+    #undef __FLT32X_EPSILON__
+    #define __FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x
+    #undef __LDBL_MAX_EXP__
+    #define __LDBL_MAX_EXP__ 16384
+    #undef __DECIMAL_BID_FORMAT__
+    #define __DECIMAL_BID_FORMAT__ 1
+    #undef __FLT64_MIN_EXP__
+    #define __FLT64_MIN_EXP__ (-1021)
+    #undef __FLT64_MIN_10_EXP__
+    #define __FLT64_MIN_10_EXP__ (-307)
+    #undef __FLT16_MIN_10_EXP__
+    #define __FLT16_MIN_10_EXP__ (-4)
+    #undef __FLT64X_DECIMAL_DIG__
+    #define __FLT64X_DECIMAL_DIG__ 21
+    #undef __DEC128_MIN__
+    #define __DEC128_MIN__ 1E-6143DL
+    #undef __REGISTER_PREFIX__
+    #define __REGISTER_PREFIX__
+    #undef __UINT16_MAX__
+    #define __UINT16_MAX__ 0xffff
+    #undef __DBL_HAS_DENORM__
+    #define __DBL_HAS_DENORM__ 1
+    #undef __FLT32_MIN__
+    #define __FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32
+    #undef __UINT8_TYPE__
+    #define __UINT8_TYPE__ unsigned char
+    #undef __FLT_DIG__
+    #define __FLT_DIG__ 6
+    #undef __NO_INLINE__
+    #define __NO_INLINE__ 1
+    #undef __DEC_EVAL_METHOD__
+    #define __DEC_EVAL_METHOD__ 2
+    #undef __i386
+    #define __i386 1
+    #undef __FLT_MANT_DIG__
+    #define __FLT_MANT_DIG__ 24
+    #undef __LDBL_DECIMAL_DIG__
+    #define __LDBL_DECIMAL_DIG__ 21
+    #undef __VERSION__
+    #define __VERSION__ "13.1.1 20230429"
+    #undef __UINT64_C
+    #define __UINT64_C(c) c ## ULL
+    #undef _STDC_PREDEF_H
+    #define _STDC_PREDEF_H 1
+    #undef __INT_LEAST32_MAX__
+    #define __INT_LEAST32_MAX__ 0x7fffffff
+    #undef __FLT128_MAX_EXP__
+    #define __FLT128_MAX_EXP__ 16384
+    #undef __FLT32_MANT_DIG__
+    #define __FLT32_MANT_DIG__ 24
+    #undef __FLOAT_WORD_ORDER__
+    #define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
+    #undef __FLT32X_MIN_EXP__
+    #define __FLT32X_MIN_EXP__ (-1021)
+    #undef i386
+    #define i386 1
+    #undef __BFLT16_MIN__
+    #define __BFLT16_MIN__ 1.17549435082228750796873653722224568e-38BF16
+    #undef __FLT128_HAS_DENORM__
+    #define __FLT128_HAS_DENORM__ 1
+    #undef __FLT32_DECIMAL_DIG__
+    #define __FLT32_DECIMAL_DIG__ 9
+    #undef __FLT128_DIG__
+    #define __FLT128_DIG__ 33
+    #undef __INT32_C
+    #define __INT32_C(c) c
+    #undef __DEC64_EPSILON__
+    #define __DEC64_EPSILON__ 1E-15DD
+    #undef __ORDER_PDP_ENDIAN__
+    #define __ORDER_PDP_ENDIAN__ 3412
+    #undef __DEC128_MIN_EXP__
+    #define __DEC128_MIN_EXP__ (-6142)
+    #undef __code_model_32__
+    #define __code_model_32__ 1
+    #undef __DEC128_MAX__
+    #define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
+    #undef __INT_FAST32_TYPE__
+    #define __INT_FAST32_TYPE__ int
+    #undef __UINT_LEAST16_TYPE__
+    #define __UINT_LEAST16_TYPE__ short unsigned int
+    #undef __DEC128_MAX_EXP__
+    #define __DEC128_MAX_EXP__ 6145
+    #undef unix
+    #define unix 1
+    #undef __i386__
+    #define __i386__ 1
+    #undef __UINT64_MAX__
+    #define __UINT64_MAX__ 0xffffffffffffffffULL
+    #undef __FLT_IS_IEC_60559__
+    #define __FLT_IS_IEC_60559__ 1
+    #undef __GNUC_WIDE_EXECUTION_CHARSET_NAME
+    #define __GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE"
+    #undef __FLT64X_DIG__
+    #define __FLT64X_DIG__ 18
+    #undef __INT8_TYPE__
+    #define __INT8_TYPE__ signed char
+    #undef __ELF__
+    #define __ELF__ 1
+    #undef __UINT32_TYPE__
+    #define __UINT32_TYPE__ unsigned int
+    #undef __BFLT16_HAS_QUIET_NAN__
+    #define __BFLT16_HAS_QUIET_NAN__ 1
+    #undef __FLT_RADIX__
+    #define __FLT_RADIX__ 2
+    #undef __INT_LEAST16_TYPE__
+    #define __INT_LEAST16_TYPE__ short int
+    #undef __LDBL_EPSILON__
+    #define __LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L
+    #undef __UINTMAX_C
+    #define __UINTMAX_C(c) c ## ULL
+    #undef __FLT16_DIG__
+    #define __FLT16_DIG__ 3
+    #undef __k8
+    #define __k8 1
+    #undef __FLT32X_MIN__
+    #define __FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x
+    #undef __SIG_ATOMIC_MAX__
+    #define __SIG_ATOMIC_MAX__ 0x7fffffff
+    #undef __USER_LABEL_PREFIX__
+    #define __USER_LABEL_PREFIX__
+    #undef __SIZEOF_PTRDIFF_T__
+    #define __SIZEOF_PTRDIFF_T__ 4
+    #undef __FLT64X_HAS_INFINITY__
+    #define __FLT64X_HAS_INFINITY__ 1
+    #undef __FLT32_HAS_INFINITY__
+    #define __FLT32_HAS_INFINITY__ 1
+    #undef __SIZEOF_LONG__
+    #define __SIZEOF_LONG__ 4
+    #undef __LDBL_DIG__
+    #define __LDBL_DIG__ 18
+    #undef __FLT64_IS_IEC_60559__
+    #define __FLT64_IS_IEC_60559__ 1
+    #undef __FLT16_IS_IEC_60559__
+    #define __FLT16_IS_IEC_60559__ 1
+    #undef __FLT16_MAX_EXP__
+    #define __FLT16_MAX_EXP__ 16
+    #undef __DEC32_SUBNORMAL_MIN__
+    #define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
+    #undef __INT_FAST16_MAX__
+    #define __INT_FAST16_MAX__ 0x7fffffff
+    #undef __FLT64_DIG__
+    #define __FLT64_DIG__ 15
+    #undef __UINT_FAST32_MAX__
+    #define __UINT_FAST32_MAX__ 0xffffffffU
+    #undef __UINT_LEAST64_TYPE__
+    #define __UINT_LEAST64_TYPE__ long long unsigned int
+    #undef __FLT16_EPSILON__
+    #define __FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16
+    #undef __ILP32__
+    #define __ILP32__ 1
+    #undef __FLT_HAS_QUIET_NAN__
+    #define __FLT_HAS_QUIET_NAN__ 1
+    #undef __FLT_MAX_10_EXP__
+    #define __FLT_MAX_10_EXP__ 38
+    #undef __LONG_MAX__
+    #define __LONG_MAX__ 0x7fffffffL
+    #undef __FLT64X_HAS_DENORM__
+    #define __FLT64X_HAS_DENORM__ 1
+    #undef __DEC128_SUBNORMAL_MIN__
+    #define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
+    #undef __FLT_HAS_INFINITY__
+    #define __FLT_HAS_INFINITY__ 1
+    #undef __GNUC_EXECUTION_CHARSET_NAME
+    #define __GNUC_EXECUTION_CHARSET_NAME "UTF-8"
+    #undef _ILP32
+    #define _ILP32 1
+    #undef __UINT_FAST16_TYPE__
+    #define __UINT_FAST16_TYPE__ unsigned int
+    #undef __DEC64_MAX__
+    #define __DEC64_MAX__ 9.999999999999999E384DD
+    #undef __INT_FAST32_WIDTH__
+    #define __INT_FAST32_WIDTH__ 32
+    #undef __CHAR16_TYPE__
+    #define __CHAR16_TYPE__ short unsigned int
+    #undef __PRAGMA_REDEFINE_EXTNAME
+    #define __PRAGMA_REDEFINE_EXTNAME 1
+    #undef __SIZE_WIDTH__
+    #define __SIZE_WIDTH__ 32
+    #undef __SEG_FS
+    #define __SEG_FS 1
+    #undef __INT_LEAST16_MAX__
+    #define __INT_LEAST16_MAX__ 0x7fff
+    #undef __FLT16_NORM_MAX__
+    #define __FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16
+    #undef __DEC64_MANT_DIG__
+    #define __DEC64_MANT_DIG__ 16
+    #undef __FLT32_DENORM_MIN__
+    #define __FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32
+    #undef __SIG_ATOMIC_WIDTH__
+    #define __SIG_ATOMIC_WIDTH__ 32
+    #undef __INT_LEAST64_TYPE__
+    #define __INT_LEAST64_TYPE__ long long int
+    #undef __INT16_TYPE__
+    #define __INT16_TYPE__ short int
+    #undef __INT_LEAST8_TYPE__
+    #define __INT_LEAST8_TYPE__ signed char
+    #undef __FLT16_MAX__
+    #define __FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16
+    #undef __FLT128_MIN__
+    #define __FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128
+    #undef __SIZEOF_INT__
+    #define __SIZEOF_INT__ 4
+    #undef __DEC32_MAX_EXP__
+    #define __DEC32_MAX_EXP__ 97
+    #undef __INT_FAST8_MAX__
+    #define __INT_FAST8_MAX__ 0x7f
+    #undef __FLT128_MAX__
+    #define __FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128
+    #undef __INTPTR_MAX__
+    #define __INTPTR_MAX__ 0x7fffffff
+    #undef linux
+    #define linux 1
+    #undef __FLT64_HAS_QUIET_NAN__
+    #define __FLT64_HAS_QUIET_NAN__ 1
+    #undef __FLT32_MIN_10_EXP__
+    #define __FLT32_MIN_10_EXP__ (-37)
+    #undef __FLT32X_DIG__
+    #define __FLT32X_DIG__ 15
+    #undef __UINT16_C
+    #define __UINT16_C(c) c
+    #undef __PTRDIFF_WIDTH__
+    #define __PTRDIFF_WIDTH__ 32
+    #undef __LDBL_MANT_DIG__
+    #define __LDBL_MANT_DIG__ 64
+    #undef __INT_FAST16_WIDTH__
+    #define __INT_FAST16_WIDTH__ 32
+    #undef __FLT64_HAS_INFINITY__
+    #define __FLT64_HAS_INFINITY__ 1
+    #undef __FLT64X_MAX__
+    #define __FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+    #undef __FLT16_HAS_INFINITY__
+    #define __FLT16_HAS_INFINITY__ 1
+    #undef __SIG_ATOMIC_MIN__
+    #define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
+    #undef __DEC32_MANT_DIG__
+    #define __DEC32_MANT_DIG__ 7
+    #undef __FLT16_MANT_DIG__
+    #define __FLT16_MANT_DIG__ 11
+    #undef __k8__
+    #define __k8__ 1
+    #undef __INTPTR_TYPE__
+    #define __INTPTR_TYPE__ int
+    #undef __UINT16_TYPE__
+    #define __UINT16_TYPE__ short unsigned int
+    #undef __WCHAR_TYPE__
+    #define __WCHAR_TYPE__ long int
+    #undef __pic__
+    #define __pic__ 2
+    #undef __UINTPTR_MAX__
+    #define __UINTPTR_MAX__ 0xffffffffU
+    #undef __INT_FAST64_WIDTH__
+    #define __INT_FAST64_WIDTH__ 64
+    #undef __LDBL_HAS_INFINITY__
+    #define __LDBL_HAS_INFINITY__ 1
+    #undef __INT_FAST64_MAX__
+    #define __INT_FAST64_MAX__ 0x7fffffffffffffffLL
+    #undef __FLT_NORM_MAX__
+    #define __FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F
+    #undef __FLT64X_MAX_EXP__
+    #define __FLT64X_MAX_EXP__ 16384
+    #undef __UINT_FAST64_TYPE__
+    #define __UINT_FAST64_TYPE__ long long unsigned int
+    #undef __BFLT16_MIN_EXP__
+    #define __BFLT16_MIN_EXP__ (-125)
+    #undef __INT_MAX__
+    #define __INT_MAX__ 0x7fffffff
+    #undef __linux__
+    #define __linux__ 1
+    #undef __INT64_TYPE__
+    #define __INT64_TYPE__ long long int
+    #undef __FLT_MAX_EXP__
+    #define __FLT_MAX_EXP__ 128
+    #undef __DBL_MANT_DIG__
+    #define __DBL_MANT_DIG__ 53
+    #undef __SIZEOF_FLOAT128__
+    #define __SIZEOF_FLOAT128__ 16
+    #undef __BFLT16_MANT_DIG__
+    #define __BFLT16_MANT_DIG__ 8
+    #undef __DEC64_MIN__
+    #define __DEC64_MIN__ 1E-383DD
+    #undef __WINT_TYPE__
+    #define __WINT_TYPE__ unsigned int
+    #undef __UINT_LEAST32_TYPE__
+    #define __UINT_LEAST32_TYPE__ unsigned int
+    #undef __SIZEOF_SHORT__
+    #define __SIZEOF_SHORT__ 2
+    #undef __FLT32_NORM_MAX__
+    #define __FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32
+    #undef __SSE__
+    #define __SSE__ 1
+    #undef __LDBL_MIN_EXP__
+    #define __LDBL_MIN_EXP__ (-16381)
+    #undef __FLT64_MAX__
+    #define __FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64
+    #undef __WINT_WIDTH__
+    #define __WINT_WIDTH__ 32
+    #undef __INT_LEAST8_MAX__
+    #define __INT_LEAST8_MAX__ 0x7f
+    #undef __INT_LEAST64_WIDTH__
+    #define __INT_LEAST64_WIDTH__ 64
+    #undef __FLT32X_MAX_10_EXP__
+    #define __FLT32X_MAX_10_EXP__ 308
+    #undef __FLT16_MIN__
+    #define __FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16
+    #undef __FLT64X_IS_IEC_60559__
+    #define __FLT64X_IS_IEC_60559__ 1
+    #undef __LDBL_MAX_10_EXP__
+    #define __LDBL_MAX_10_EXP__ 4932
+    #undef __ATOMIC_RELAXED
+    #define __ATOMIC_RELAXED 0
+    #undef __DBL_EPSILON__
+    #define __DBL_EPSILON__ ((double)2.22044604925031308084726333618164062e-16L)
+    #undef __INT_LEAST32_TYPE__
+    #define __INT_LEAST32_TYPE__ int
+    #undef __UINT8_C
+    #define __UINT8_C(c) c
+    #undef __FLT64_MAX_EXP__
+    #define __FLT64_MAX_EXP__ 1024
+    #undef __SIZEOF_WCHAR_T__
+    #define __SIZEOF_WCHAR_T__ 4
+    #undef __UINT64_TYPE__
+    #define __UINT64_TYPE__ long long unsigned int
+    #undef __GNUC_PATCHLEVEL__
+    #define __GNUC_PATCHLEVEL__ 1
+    #undef __FLT128_NORM_MAX__
+    #define __FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128
+    #undef __FLT64_NORM_MAX__
+    #define __FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64
+    #undef __FLT128_HAS_QUIET_NAN__
+    #define __FLT128_HAS_QUIET_NAN__ 1
+    #undef __INTMAX_MAX__
+    #define __INTMAX_MAX__ 0x7fffffffffffffffLL
+    #undef __INT_FAST8_TYPE__
+    #define __INT_FAST8_TYPE__ signed char
+    #undef __FLT64X_MIN__
+    #define __FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x
+    #undef __GNUC_STDC_INLINE__
+    #define __GNUC_STDC_INLINE__ 1
+    #undef __FLT64_HAS_DENORM__
+    #define __FLT64_HAS_DENORM__ 1
+    #undef __FLT32_EPSILON__
+    #define __FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32
+    #undef __FLT16_HAS_DENORM__
+    #define __FLT16_HAS_DENORM__ 1
+    #undef __DBL_DECIMAL_DIG__
+    #define __DBL_DECIMAL_DIG__ 17
+    #undef __INT_FAST8_WIDTH__
+    #define __INT_FAST8_WIDTH__ 8
+    #undef __FXSR__
+    #define __FXSR__ 1
+    #undef __FLT32X_MAX__
+    #define __FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x
+    #undef __DBL_NORM_MAX__
+    #define __DBL_NORM_MAX__ ((double)1.79769313486231570814527423731704357e+308L)
+    #undef __BYTE_ORDER__
+    #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+    #undef __INTMAX_WIDTH__
+    #define __INTMAX_WIDTH__ 64
+    #undef __ORDER_BIG_ENDIAN__
+    #define __ORDER_BIG_ENDIAN__ 4321
+    #undef __FLT32_DIG__
+    #define __FLT32_DIG__ 6
+    #undef __UINT32_C
+    #define __UINT32_C(c) c ## U
+    #undef __FLT_DENORM_MIN__
+    #define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F
+    #undef __INT8_MAX__
+    #define __INT8_MAX__ 0x7f
+    #undef __LONG_WIDTH__
+    #define __LONG_WIDTH__ 32
+    #undef __DBL_MIN__
+    #define __DBL_MIN__ ((double)2.22507385850720138309023271733240406e-308L)
+    #undef __PIC__
+    #define __PIC__ 2
+    #undef __INT32_MAX__
+    #define __INT32_MAX__ 0x7fffffff
+    #undef __UINT_FAST32_TYPE__
+    #define __UINT_FAST32_TYPE__ unsigned int
+    #undef __FLT32X_NORM_MAX__
+    #define __FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x
+    #undef __CHAR32_TYPE__
+    #define __CHAR32_TYPE__ unsigned int
+    #undef __FLT_MAX__
+    #define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F
+    #undef __SSE2__
+    #define __SSE2__ 1
+    #undef __INT32_TYPE__
+    #define __INT32_TYPE__ int
+    #undef __SIZEOF_DOUBLE__
+    #define __SIZEOF_DOUBLE__ 8
+    #undef __FLT_MIN_10_EXP__
+    #define __FLT_MIN_10_EXP__ (-37)
+    #undef __FLT64_MIN__
+    #define __FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64
+    #undef __INT_LEAST32_WIDTH__
+    #define __INT_LEAST32_WIDTH__ 32
+    #undef __INTMAX_TYPE__
+    #define __INTMAX_TYPE__ long long int
+    #undef __FLT32X_HAS_QUIET_NAN__
+    #define __FLT32X_HAS_QUIET_NAN__ 1
+    #undef __ATOMIC_CONSUME
+    #define __ATOMIC_CONSUME 1
+    #undef __GNUC_MINOR__
+    #define __GNUC_MINOR__ 1
+    #undef __UINTMAX_MAX__
+    #define __UINTMAX_MAX__ 0xffffffffffffffffULL
+    #undef __PIE__
+    #define __PIE__ 2
+    #undef __FLT32X_DENORM_MIN__
+    #define __FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x
+    #undef __DBL_MAX_10_EXP__
+    #define __DBL_MAX_10_EXP__ 308
+    #undef __LDBL_DENORM_MIN__
+    #define __LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L
+    #undef __INT16_C
+    #define __INT16_C(c) c
+    #undef __PTRDIFF_TYPE__
+    #define __PTRDIFF_TYPE__ int
+    #undef __FLT32X_MIN_10_EXP__
+    #define __FLT32X_MIN_10_EXP__ (-307)
+    #undef __UINTPTR_TYPE__
+    #define __UINTPTR_TYPE__ unsigned int
+    #undef __DEC64_SUBNORMAL_MIN__
+    #define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
+    #undef __DEC128_MANT_DIG__
+    #define __DEC128_MANT_DIG__ 34
+    #undef __LDBL_MIN_10_EXP__
+    #define __LDBL_MIN_10_EXP__ (-4931)
+    #undef __SIZEOF_LONG_LONG__
+    #define __SIZEOF_LONG_LONG__ 8
+    #undef __FLT128_DECIMAL_DIG__
+    #define __FLT128_DECIMAL_DIG__ 36
+    #undef __FLT32_HAS_QUIET_NAN__
+    #define __FLT32_HAS_QUIET_NAN__ 1
+    #undef __FLT_DECIMAL_DIG__
+    #define __FLT_DECIMAL_DIG__ 9
+    #undef __UINT_FAST16_MAX__
+    #define __UINT_FAST16_MAX__ 0xffffffffU
+    #undef __LDBL_NORM_MAX__
+    #define __LDBL_NORM_MAX__ 1.18973149535723176502126385303097021e+4932L
+    #undef __SIZE_MAX__
+    #define __SIZE_MAX__ 0xffffffffU
+    #undef __UINT_FAST8_TYPE__
+    #define __UINT_FAST8_TYPE__ unsigned char
+    #undef __ATOMIC_ACQ_REL
+    #define __ATOMIC_ACQ_REL 4
+    #undef __ATOMIC_RELEASE
+    #define __ATOMIC_RELEASE 3
+eof: (-1)
+errno:
+    e2big: '7'
+    eacces: '13'
+    eaddrinuse: '98'
+    eaddrnotavail: '99'
+    eafnosupport: '97'
+    eagain: '11'
+    ealready: '114'
+    ebade: '52'
+    ebadf: '9'
+    ebadfd: '77'
+    ebadmsg: '74'
+    ebadr: '53'
+    ebadrqc: '56'
+    ebadslt: '57'
+    ebusy: '16'
+    ecanceled: '125'
+    echild: '10'
+    echrng: '44'
+    ecomm: '70'
+    econnaborted: '103'
+    econnrefused: '111'
+    econnreset: '104'
+    edeadlk: '35'
+    edeadlock: '35'
+    edestaddrreq: '89'
+    edom: '33'
+    edquot: '122'
+    eexist: '17'
+    efault: '14'
+    efbig: '27'
+    ehostdown: '112'
+    ehostunreach: '113'
+    eidrm: '43'
+    eilseq: '84'
+    einprogress: '115'
+    eintr: '4'
+    einval: '22'
+    eio: '5'
+    eisconn: '106'
+    eisdir: '21'
+    eisnam: '120'
+    ekeyexpired: '127'
+    ekeyrejected: '129'
+    ekeyrevoked: '128'
+    el2hlt: '51'
+    el2nsync: '45'
+    el3hlt: '46'
+    el3rst: '47'
+    elibacc: '79'
+    elibbad: '80'
+    elibexec: '83'
+    elibmax: '82'
+    elibscn: '81'
+    eloop: '40'
+    emediumtype: '124'
+    emfile: '24'
+    emlink: '31'
+    emsgsize: '90'
+    emultihop: '72'
+    enametoolong: '36'
+    enetdown: '100'
+    enetreset: '102'
+    enetunreach: '101'
+    enfile: '23'
+    enobufs: '105'
+    enodata: '61'
+    enodev: '19'
+    enoent: '2'
+    enoexec: '8'
+    enokey: '126'
+    enolck: '37'
+    enolink: '67'
+    enomedium: '123'
+    enomem: '12'
+    enomsg: '42'
+    enonet: '64'
+    enopkg: '65'
+    enoprotoopt: '92'
+    enospc: '28'
+    enosr: '63'
+    enostr: '60'
+    enosys: '38'
+    enotblk: '15'
+    enotconn: '107'
+    enotdir: '20'
+    enotempty: '39'
+    enotrecoverable: '131'
+    enotsock: '88'
+    enotsup: '95'
+    enotty: '25'
+    enotuniq: '76'
+    enxio: '6'
+    eopnotsupp: '95'
+    eoverflow: '75'
+    eownerdead: '130'
+    eperm: '1'
+    epfnosupport: '96'
+    epipe: '32'
+    eproto: '71'
+    eprotonosupport: '93'
+    eprototype: '91'
+    erange: '34'
+    eremchg: '78'
+    eremote: '66'
+    eremoteio: '121'
+    erestart: '85'
+    erofs: '30'
+    eshutdown: '108'
+    esocktnosupport: '94'
+    espipe: '29'
+    esrch: '3'
+    estale: '116'
+    estrpipe: '86'
+    etime: '62'
+    etimedout: '110'
+    etxtbsy: '26'
+    euclean: '117'
+    eunatch: '49'
+    eusers: '87'
+    ewouldblock: '11'
+    exdev: '18'
+    exfull: '54'
+filename_max: '4096'
+fopen_max: '16'
+has__builtin_va_list: true
+host_name_max: '64'
+int_fast16_t: int
+int_fast32_t: int
+int_fast64_t: long long
+int_fast8_t: signed char
+intptr_t: int
+l_tmpnam: '20'
+little_endian: true
+machdep_name: machdep_x86_32
+mb_cur_max: ((size_t) 16 )
+nsig: (64 + 1)
+path_max: '4096'
+posix_version: 200809L
+ptrdiff_t: int
+rand_max: '2147483647'
+sig_atomic_t: int
+size_t: unsigned int
+sizeof_double: 8
+sizeof_float: 4
+sizeof_fun: -1
+sizeof_int: 4
+sizeof_long: 4
+sizeof_longdouble: 12
+sizeof_longlong: 8
+sizeof_ptr: 4
+sizeof_short: 2
+sizeof_void: -1
+ssize_t: int
+time_t: long
+tmp_max: '238328'
+tty_name_max: '32'
+uint_fast16_t: unsigned int
+uint_fast32_t: unsigned int
+uint_fast64_t: unsigned long long
+uint_fast8_t: unsigned char
+uintptr_t: unsigned int
+version: gcc (GCC) 13.1.1 20230429
+wchar_t: long
+weof: (0xffffffffu)
+wint_t: unsigned int
+wordsize: '32'
diff --git a/share/machdeps/machdep_x86_64.yaml b/share/machdeps/machdep_x86_64.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4bea3f923dd78d231b2831b93e8d462d6ad246f3
--- /dev/null
+++ b/share/machdeps/machdep_x86_64.yaml
@@ -0,0 +1,923 @@
+alignof_aligned: 16
+alignof_double: 8
+alignof_float: 4
+alignof_fun: -1
+alignof_int: 4
+alignof_long: 8
+alignof_longdouble: 16
+alignof_longlong: 8
+alignof_ptr: 8
+alignof_short: 2
+alignof_str: 1
+bufsiz: '8192'
+char_is_unsigned: false
+compiler: generic
+cpp_arch_flags:
+- -m64
+custom_defs: |
+    #undef __DBL_MIN_EXP__
+    #define __DBL_MIN_EXP__ (-1021)
+    #undef __UINT_LEAST16_MAX__
+    #define __UINT_LEAST16_MAX__ 0xffff
+    #undef __FLT16_HAS_QUIET_NAN__
+    #define __FLT16_HAS_QUIET_NAN__ 1
+    #undef __ATOMIC_ACQUIRE
+    #define __ATOMIC_ACQUIRE 2
+    #undef __FLT128_MAX_10_EXP__
+    #define __FLT128_MAX_10_EXP__ 4932
+    #undef __FLT_MIN__
+    #define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F
+    #undef __UINT_LEAST8_TYPE__
+    #define __UINT_LEAST8_TYPE__ unsigned char
+    #undef __SIZEOF_FLOAT80__
+    #define __SIZEOF_FLOAT80__ 16
+    #undef __BFLT16_DENORM_MIN__
+    #define __BFLT16_DENORM_MIN__ 9.18354961579912115600575419704879436e-41BF16
+    #undef __INTMAX_C
+    #define __INTMAX_C(c) c ## L
+    #undef __CHAR_BIT__
+    #define __CHAR_BIT__ 8
+    #undef __UINT8_MAX__
+    #define __UINT8_MAX__ 0xff
+    #undef __SCHAR_WIDTH__
+    #define __SCHAR_WIDTH__ 8
+    #undef __WINT_MAX__
+    #define __WINT_MAX__ 0xffffffffU
+    #undef __FLT32_MIN_EXP__
+    #define __FLT32_MIN_EXP__ (-125)
+    #undef __BFLT16_NORM_MAX__
+    #define __BFLT16_NORM_MAX__ 3.38953138925153547590470800371487867e+38BF16
+    #undef __BFLT16_MIN_10_EXP__
+    #define __BFLT16_MIN_10_EXP__ (-37)
+    #undef __ORDER_LITTLE_ENDIAN__
+    #define __ORDER_LITTLE_ENDIAN__ 1234
+    #undef __WCHAR_MAX__
+    #define __WCHAR_MAX__ 0x7fffffff
+    #undef __FLT32X_DECIMAL_DIG__
+    #define __FLT32X_DECIMAL_DIG__ 17
+    #undef __FLT_EVAL_METHOD__
+    #define __FLT_EVAL_METHOD__ 0
+    #undef __FLT64_DECIMAL_DIG__
+    #define __FLT64_DECIMAL_DIG__ 17
+    #undef __UINT_FAST64_MAX__
+    #define __UINT_FAST64_MAX__ 0xffffffffffffffffUL
+    #undef __SIG_ATOMIC_TYPE__
+    #define __SIG_ATOMIC_TYPE__ int
+    #undef __DBL_MIN_10_EXP__
+    #define __DBL_MIN_10_EXP__ (-307)
+    #undef __FINITE_MATH_ONLY__
+    #define __FINITE_MATH_ONLY__ 0
+    #undef __FLT32X_MAX_EXP__
+    #define __FLT32X_MAX_EXP__ 1024
+    #undef __FLT32_HAS_DENORM__
+    #define __FLT32_HAS_DENORM__ 1
+    #undef __UINT_FAST8_MAX__
+    #define __UINT_FAST8_MAX__ 0xff
+    #undef __FLT32_MAX_10_EXP__
+    #define __FLT32_MAX_10_EXP__ 38
+    #undef __DEC64_MAX_EXP__
+    #define __DEC64_MAX_EXP__ 385
+    #undef __INT8_C
+    #define __INT8_C(c) c
+    #undef __INT_LEAST8_WIDTH__
+    #define __INT_LEAST8_WIDTH__ 8
+    #undef __UINT_LEAST64_MAX__
+    #define __UINT_LEAST64_MAX__ 0xffffffffffffffffUL
+    #undef __SHRT_MAX__
+    #define __SHRT_MAX__ 0x7fff
+    #undef __LDBL_MAX__
+    #define __LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L
+    #undef __FLT64X_MAX_10_EXP__
+    #define __FLT64X_MAX_10_EXP__ 4932
+    #undef __BFLT16_MAX_10_EXP__
+    #define __BFLT16_MAX_10_EXP__ 38
+    #undef __BFLT16_MAX_EXP__
+    #define __BFLT16_MAX_EXP__ 128
+    #undef __LDBL_IS_IEC_60559__
+    #define __LDBL_IS_IEC_60559__ 1
+    #undef __FLT64X_HAS_QUIET_NAN__
+    #define __FLT64X_HAS_QUIET_NAN__ 1
+    #undef __UINT_LEAST8_MAX__
+    #define __UINT_LEAST8_MAX__ 0xff
+    #undef __FLT128_DENORM_MIN__
+    #define __FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128
+    #undef __UINTMAX_TYPE__
+    #define __UINTMAX_TYPE__ long unsigned int
+    #undef __BFLT16_DECIMAL_DIG__
+    #define __BFLT16_DECIMAL_DIG__ 4
+    #undef __linux
+    #define __linux 1
+    #undef __DEC32_EPSILON__
+    #define __DEC32_EPSILON__ 1E-6DF
+    #undef __FLT_EVAL_METHOD_TS_18661_3__
+    #define __FLT_EVAL_METHOD_TS_18661_3__ 0
+    #undef __UINT32_MAX__
+    #define __UINT32_MAX__ 0xffffffffU
+    #undef __DBL_DENORM_MIN__
+    #define __DBL_DENORM_MIN__ ((double)4.94065645841246544176568792868221372e-324L)
+    #undef __FLT128_MIN_EXP__
+    #define __FLT128_MIN_EXP__ (-16381)
+    #undef __WINT_MIN__
+    #define __WINT_MIN__ 0U
+    #undef __FLT128_MIN_10_EXP__
+    #define __FLT128_MIN_10_EXP__ (-4931)
+    #undef __FLT32X_IS_IEC_60559__
+    #define __FLT32X_IS_IEC_60559__ 1
+    #undef __INT_LEAST16_WIDTH__
+    #define __INT_LEAST16_WIDTH__ 16
+    #undef __SCHAR_MAX__
+    #define __SCHAR_MAX__ 0x7f
+    #undef __FLT128_MANT_DIG__
+    #define __FLT128_MANT_DIG__ 113
+    #undef __WCHAR_MIN__
+    #define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
+    #undef __INT64_C
+    #define __INT64_C(c) c ## L
+    #undef __SSP_STRONG__
+    #define __SSP_STRONG__ 3
+    #undef __ATOMIC_SEQ_CST
+    #define __ATOMIC_SEQ_CST 5
+    #undef __unix
+    #define __unix 1
+    #undef __INT_LEAST64_MAX__
+    #define __INT_LEAST64_MAX__ 0x7fffffffffffffffL
+    #undef __FLT32X_MANT_DIG__
+    #define __FLT32X_MANT_DIG__ 53
+    #undef __FLT64X_EPSILON__
+    #define __FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x
+    #undef __DEC64_MIN_EXP__
+    #define __DEC64_MIN_EXP__ (-382)
+    #undef __DBL_DIG__
+    #define __DBL_DIG__ 15
+    #undef __FLT_EPSILON__
+    #define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F
+    #undef __SHRT_WIDTH__
+    #define __SHRT_WIDTH__ 16
+    #undef __FLT32_IS_IEC_60559__
+    #define __FLT32_IS_IEC_60559__ 1
+    #undef __LDBL_MIN__
+    #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
+    #undef __DBL_IS_IEC_60559__
+    #define __DBL_IS_IEC_60559__ 1
+    #undef __DEC32_MAX__
+    #define __DEC32_MAX__ 9.999999E96DF
+    #undef __FLT64X_DENORM_MIN__
+    #define __FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x
+    #undef __FLT32X_HAS_INFINITY__
+    #define __FLT32X_HAS_INFINITY__ 1
+    #undef __unix__
+    #define __unix__ 1
+    #undef __INT_WIDTH__
+    #define __INT_WIDTH__ 32
+    #undef __DECIMAL_DIG__
+    #define __DECIMAL_DIG__ 21
+    #undef __FLT64_EPSILON__
+    #define __FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64
+    #undef __gnu_linux__
+    #define __gnu_linux__ 1
+    #undef __FLT128_IS_IEC_60559__
+    #define __FLT128_IS_IEC_60559__ 1
+    #undef __FLT64X_MIN_10_EXP__
+    #define __FLT64X_MIN_10_EXP__ (-4931)
+    #undef __LDBL_HAS_QUIET_NAN__
+    #define __LDBL_HAS_QUIET_NAN__ 1
+    #undef __FLT16_MIN_EXP__
+    #define __FLT16_MIN_EXP__ (-13)
+    #undef __FLT64_MANT_DIG__
+    #define __FLT64_MANT_DIG__ 53
+    #undef __FLT64X_MANT_DIG__
+    #define __FLT64X_MANT_DIG__ 64
+    #undef __BFLT16_DIG__
+    #define __BFLT16_DIG__ 2
+    #undef __GNUC__
+    #define __GNUC__ 13
+    #undef __pie__
+    #define __pie__ 2
+    #undef __MMX__
+    #define __MMX__ 1
+    #undef __FLT_HAS_DENORM__
+    #define __FLT_HAS_DENORM__ 1
+    #undef __SIZEOF_LONG_DOUBLE__
+    #define __SIZEOF_LONG_DOUBLE__ 16
+    #undef __BIGGEST_ALIGNMENT__
+    #define __BIGGEST_ALIGNMENT__ 16
+    #undef __FLT64_MAX_10_EXP__
+    #define __FLT64_MAX_10_EXP__ 308
+    #undef __BFLT16_IS_IEC_60559__
+    #define __BFLT16_IS_IEC_60559__ 0
+    #undef __FLT16_MAX_10_EXP__
+    #define __FLT16_MAX_10_EXP__ 4
+    #undef __DBL_MAX__
+    #define __DBL_MAX__ ((double)1.79769313486231570814527423731704357e+308L)
+    #undef __INT_FAST32_MAX__
+    #define __INT_FAST32_MAX__ 0x7fffffffffffffffL
+    #undef __DBL_HAS_INFINITY__
+    #define __DBL_HAS_INFINITY__ 1
+    #undef __INT64_MAX__
+    #define __INT64_MAX__ 0x7fffffffffffffffL
+    #undef __SIZEOF_FLOAT__
+    #define __SIZEOF_FLOAT__ 4
+    #undef __HAVE_SPECULATION_SAFE_VALUE
+    #define __HAVE_SPECULATION_SAFE_VALUE 1
+    #undef __DEC32_MIN_EXP__
+    #define __DEC32_MIN_EXP__ (-94)
+    #undef __INTPTR_WIDTH__
+    #define __INTPTR_WIDTH__ 64
+    #undef __UINT_LEAST32_MAX__
+    #define __UINT_LEAST32_MAX__ 0xffffffffU
+    #undef __FLT32X_HAS_DENORM__
+    #define __FLT32X_HAS_DENORM__ 1
+    #undef __INT_FAST16_TYPE__
+    #define __INT_FAST16_TYPE__ long int
+    #undef __MMX_WITH_SSE__
+    #define __MMX_WITH_SSE__ 1
+    #undef __LDBL_HAS_DENORM__
+    #define __LDBL_HAS_DENORM__ 1
+    #undef __SEG_GS
+    #define __SEG_GS 1
+    #undef __BFLT16_EPSILON__
+    #define __BFLT16_EPSILON__ 7.81250000000000000000000000000000000e-3BF16
+    #undef __FLT128_HAS_INFINITY__
+    #define __FLT128_HAS_INFINITY__ 1
+    #undef __DEC32_MIN__
+    #define __DEC32_MIN__ 1E-95DF
+    #undef __DBL_MAX_EXP__
+    #define __DBL_MAX_EXP__ 1024
+    #undef __WCHAR_WIDTH__
+    #define __WCHAR_WIDTH__ 32
+    #undef __FLT32_MAX__
+    #define __FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32
+    #undef __DEC128_EPSILON__
+    #define __DEC128_EPSILON__ 1E-33DL
+    #undef __FLT16_DECIMAL_DIG__
+    #define __FLT16_DECIMAL_DIG__ 5
+    #undef __SSE2_MATH__
+    #define __SSE2_MATH__ 1
+    #undef __ATOMIC_HLE_RELEASE
+    #define __ATOMIC_HLE_RELEASE 131072
+    #undef __PTRDIFF_MAX__
+    #define __PTRDIFF_MAX__ 0x7fffffffffffffffL
+    #undef __amd64
+    #define __amd64 1
+    #undef __ATOMIC_HLE_ACQUIRE
+    #define __ATOMIC_HLE_ACQUIRE 65536
+    #undef __LONG_LONG_MAX__
+    #define __LONG_LONG_MAX__ 0x7fffffffffffffffLL
+    #undef __SIZEOF_SIZE_T__
+    #define __SIZEOF_SIZE_T__ 8
+    #undef __BFLT16_HAS_INFINITY__
+    #define __BFLT16_HAS_INFINITY__ 1
+    #undef __FLT64X_MIN_EXP__
+    #define __FLT64X_MIN_EXP__ (-16381)
+    #undef __SIZEOF_WINT_T__
+    #define __SIZEOF_WINT_T__ 4
+    #undef __LONG_LONG_WIDTH__
+    #define __LONG_LONG_WIDTH__ 64
+    #undef __FLT32_MAX_EXP__
+    #define __FLT32_MAX_EXP__ 128
+    #undef __GXX_ABI_VERSION
+    #define __GXX_ABI_VERSION 1018
+    #undef __FLT_MIN_EXP__
+    #define __FLT_MIN_EXP__ (-125)
+    #undef __INT16_MAX__
+    #define __INT16_MAX__ 0x7fff
+    #undef __x86_64
+    #define __x86_64 1
+    #undef __INT_FAST64_TYPE__
+    #define __INT_FAST64_TYPE__ long int
+    #undef __BFLT16_MAX__
+    #define __BFLT16_MAX__ 3.38953138925153547590470800371487867e+38BF16
+    #undef __BFLT16_HAS_DENORM__
+    #define __BFLT16_HAS_DENORM__ 1
+    #undef __FLT64_DENORM_MIN__
+    #define __FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64
+    #undef __FLT16_DENORM_MIN__
+    #define __FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16
+    #undef __FLT128_EPSILON__
+    #define __FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128
+    #undef __FLT64X_NORM_MAX__
+    #define __FLT64X_NORM_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+    #undef __SIZEOF_POINTER__
+    #define __SIZEOF_POINTER__ 8
+    #undef __SIZE_TYPE__
+    #define __SIZE_TYPE__ long unsigned int
+    #undef __LP64__
+    #define __LP64__ 1
+    #undef __DBL_HAS_QUIET_NAN__
+    #define __DBL_HAS_QUIET_NAN__ 1
+    #undef __FLT32X_EPSILON__
+    #define __FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x
+    #undef __LDBL_MAX_EXP__
+    #define __LDBL_MAX_EXP__ 16384
+    #undef __DECIMAL_BID_FORMAT__
+    #define __DECIMAL_BID_FORMAT__ 1
+    #undef __FLT64_MIN_EXP__
+    #define __FLT64_MIN_EXP__ (-1021)
+    #undef __FLT64_MIN_10_EXP__
+    #define __FLT64_MIN_10_EXP__ (-307)
+    #undef __FLT16_MIN_10_EXP__
+    #define __FLT16_MIN_10_EXP__ (-4)
+    #undef __FLT64X_DECIMAL_DIG__
+    #define __FLT64X_DECIMAL_DIG__ 21
+    #undef __DEC128_MIN__
+    #define __DEC128_MIN__ 1E-6143DL
+    #undef __REGISTER_PREFIX__
+    #define __REGISTER_PREFIX__
+    #undef __UINT16_MAX__
+    #define __UINT16_MAX__ 0xffff
+    #undef __DBL_HAS_DENORM__
+    #define __DBL_HAS_DENORM__ 1
+    #undef __FLT32_MIN__
+    #define __FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32
+    #undef __UINT8_TYPE__
+    #define __UINT8_TYPE__ unsigned char
+    #undef __FLT_DIG__
+    #define __FLT_DIG__ 6
+    #undef __NO_INLINE__
+    #define __NO_INLINE__ 1
+    #undef __DEC_EVAL_METHOD__
+    #define __DEC_EVAL_METHOD__ 2
+    #undef __FLT_MANT_DIG__
+    #define __FLT_MANT_DIG__ 24
+    #undef __LDBL_DECIMAL_DIG__
+    #define __LDBL_DECIMAL_DIG__ 21
+    #undef __VERSION__
+    #define __VERSION__ "13.1.1 20230429"
+    #undef __UINT64_C
+    #define __UINT64_C(c) c ## UL
+    #undef _STDC_PREDEF_H
+    #define _STDC_PREDEF_H 1
+    #undef __INT_LEAST32_MAX__
+    #define __INT_LEAST32_MAX__ 0x7fffffff
+    #undef __FLT128_MAX_EXP__
+    #define __FLT128_MAX_EXP__ 16384
+    #undef __FLT32_MANT_DIG__
+    #define __FLT32_MANT_DIG__ 24
+    #undef __FLOAT_WORD_ORDER__
+    #define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
+    #undef __FLT32X_MIN_EXP__
+    #define __FLT32X_MIN_EXP__ (-1021)
+    #undef __BFLT16_MIN__
+    #define __BFLT16_MIN__ 1.17549435082228750796873653722224568e-38BF16
+    #undef __FLT128_HAS_DENORM__
+    #define __FLT128_HAS_DENORM__ 1
+    #undef __FLT32_DECIMAL_DIG__
+    #define __FLT32_DECIMAL_DIG__ 9
+    #undef __FLT128_DIG__
+    #define __FLT128_DIG__ 33
+    #undef __INT32_C
+    #define __INT32_C(c) c
+    #undef __DEC64_EPSILON__
+    #define __DEC64_EPSILON__ 1E-15DD
+    #undef __ORDER_PDP_ENDIAN__
+    #define __ORDER_PDP_ENDIAN__ 3412
+    #undef __DEC128_MIN_EXP__
+    #define __DEC128_MIN_EXP__ (-6142)
+    #undef __DEC128_MAX__
+    #define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
+    #undef __INT_FAST32_TYPE__
+    #define __INT_FAST32_TYPE__ long int
+    #undef __UINT_LEAST16_TYPE__
+    #define __UINT_LEAST16_TYPE__ short unsigned int
+    #undef __DEC128_MAX_EXP__
+    #define __DEC128_MAX_EXP__ 6145
+    #undef unix
+    #define unix 1
+    #undef __UINT64_MAX__
+    #define __UINT64_MAX__ 0xffffffffffffffffUL
+    #undef __FLT_IS_IEC_60559__
+    #define __FLT_IS_IEC_60559__ 1
+    #undef __GNUC_WIDE_EXECUTION_CHARSET_NAME
+    #define __GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE"
+    #undef __FLT64X_DIG__
+    #define __FLT64X_DIG__ 18
+    #undef __INT8_TYPE__
+    #define __INT8_TYPE__ signed char
+    #undef __ELF__
+    #define __ELF__ 1
+    #undef __UINT32_TYPE__
+    #define __UINT32_TYPE__ unsigned int
+    #undef __BFLT16_HAS_QUIET_NAN__
+    #define __BFLT16_HAS_QUIET_NAN__ 1
+    #undef __FLT_RADIX__
+    #define __FLT_RADIX__ 2
+    #undef __INT_LEAST16_TYPE__
+    #define __INT_LEAST16_TYPE__ short int
+    #undef __LDBL_EPSILON__
+    #define __LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L
+    #undef __UINTMAX_C
+    #define __UINTMAX_C(c) c ## UL
+    #undef __FLT16_DIG__
+    #define __FLT16_DIG__ 3
+    #undef __SSE_MATH__
+    #define __SSE_MATH__ 1
+    #undef __k8
+    #define __k8 1
+    #undef __FLT32X_MIN__
+    #define __FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x
+    #undef __SIG_ATOMIC_MAX__
+    #define __SIG_ATOMIC_MAX__ 0x7fffffff
+    #undef __USER_LABEL_PREFIX__
+    #define __USER_LABEL_PREFIX__
+    #undef __SIZEOF_PTRDIFF_T__
+    #define __SIZEOF_PTRDIFF_T__ 8
+    #undef __FLT64X_HAS_INFINITY__
+    #define __FLT64X_HAS_INFINITY__ 1
+    #undef __FLT32_HAS_INFINITY__
+    #define __FLT32_HAS_INFINITY__ 1
+    #undef __SIZEOF_LONG__
+    #define __SIZEOF_LONG__ 8
+    #undef __LDBL_DIG__
+    #define __LDBL_DIG__ 18
+    #undef __FLT64_IS_IEC_60559__
+    #define __FLT64_IS_IEC_60559__ 1
+    #undef __x86_64__
+    #define __x86_64__ 1
+    #undef __FLT16_IS_IEC_60559__
+    #define __FLT16_IS_IEC_60559__ 1
+    #undef __FLT16_MAX_EXP__
+    #define __FLT16_MAX_EXP__ 16
+    #undef __DEC32_SUBNORMAL_MIN__
+    #define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
+    #undef __INT_FAST16_MAX__
+    #define __INT_FAST16_MAX__ 0x7fffffffffffffffL
+    #undef __FLT64_DIG__
+    #define __FLT64_DIG__ 15
+    #undef __UINT_FAST32_MAX__
+    #define __UINT_FAST32_MAX__ 0xffffffffffffffffUL
+    #undef __UINT_LEAST64_TYPE__
+    #define __UINT_LEAST64_TYPE__ long unsigned int
+    #undef __FLT16_EPSILON__
+    #define __FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16
+    #undef __FLT_HAS_QUIET_NAN__
+    #define __FLT_HAS_QUIET_NAN__ 1
+    #undef __FLT_MAX_10_EXP__
+    #define __FLT_MAX_10_EXP__ 38
+    #undef __LONG_MAX__
+    #define __LONG_MAX__ 0x7fffffffffffffffL
+    #undef __FLT64X_HAS_DENORM__
+    #define __FLT64X_HAS_DENORM__ 1
+    #undef __DEC128_SUBNORMAL_MIN__
+    #define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
+    #undef __FLT_HAS_INFINITY__
+    #define __FLT_HAS_INFINITY__ 1
+    #undef __GNUC_EXECUTION_CHARSET_NAME
+    #define __GNUC_EXECUTION_CHARSET_NAME "UTF-8"
+    #undef __UINT_FAST16_TYPE__
+    #define __UINT_FAST16_TYPE__ long unsigned int
+    #undef __DEC64_MAX__
+    #define __DEC64_MAX__ 9.999999999999999E384DD
+    #undef __INT_FAST32_WIDTH__
+    #define __INT_FAST32_WIDTH__ 64
+    #undef __CHAR16_TYPE__
+    #define __CHAR16_TYPE__ short unsigned int
+    #undef __PRAGMA_REDEFINE_EXTNAME
+    #define __PRAGMA_REDEFINE_EXTNAME 1
+    #undef __SIZE_WIDTH__
+    #define __SIZE_WIDTH__ 64
+    #undef __SEG_FS
+    #define __SEG_FS 1
+    #undef __INT_LEAST16_MAX__
+    #define __INT_LEAST16_MAX__ 0x7fff
+    #undef __FLT16_NORM_MAX__
+    #define __FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16
+    #undef __DEC64_MANT_DIG__
+    #define __DEC64_MANT_DIG__ 16
+    #undef __FLT32_DENORM_MIN__
+    #define __FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32
+    #undef __SIG_ATOMIC_WIDTH__
+    #define __SIG_ATOMIC_WIDTH__ 32
+    #undef __INT_LEAST64_TYPE__
+    #define __INT_LEAST64_TYPE__ long int
+    #undef __INT16_TYPE__
+    #define __INT16_TYPE__ short int
+    #undef __INT_LEAST8_TYPE__
+    #define __INT_LEAST8_TYPE__ signed char
+    #undef __FLT16_MAX__
+    #define __FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16
+    #undef __FLT128_MIN__
+    #define __FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128
+    #undef __SIZEOF_INT__
+    #define __SIZEOF_INT__ 4
+    #undef __DEC32_MAX_EXP__
+    #define __DEC32_MAX_EXP__ 97
+    #undef __INT_FAST8_MAX__
+    #define __INT_FAST8_MAX__ 0x7f
+    #undef __FLT128_MAX__
+    #define __FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128
+    #undef __INTPTR_MAX__
+    #define __INTPTR_MAX__ 0x7fffffffffffffffL
+    #undef linux
+    #define linux 1
+    #undef __FLT64_HAS_QUIET_NAN__
+    #define __FLT64_HAS_QUIET_NAN__ 1
+    #undef __FLT32_MIN_10_EXP__
+    #define __FLT32_MIN_10_EXP__ (-37)
+    #undef __FLT32X_DIG__
+    #define __FLT32X_DIG__ 15
+    #undef __UINT16_C
+    #define __UINT16_C(c) c
+    #undef __PTRDIFF_WIDTH__
+    #define __PTRDIFF_WIDTH__ 64
+    #undef __LDBL_MANT_DIG__
+    #define __LDBL_MANT_DIG__ 64
+    #undef __INT_FAST16_WIDTH__
+    #define __INT_FAST16_WIDTH__ 64
+    #undef __FLT64_HAS_INFINITY__
+    #define __FLT64_HAS_INFINITY__ 1
+    #undef __FLT64X_MAX__
+    #define __FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+    #undef __FLT16_HAS_INFINITY__
+    #define __FLT16_HAS_INFINITY__ 1
+    #undef __SIG_ATOMIC_MIN__
+    #define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
+    #undef __code_model_small__
+    #define __code_model_small__ 1
+    #undef __DEC32_MANT_DIG__
+    #define __DEC32_MANT_DIG__ 7
+    #undef __FLT16_MANT_DIG__
+    #define __FLT16_MANT_DIG__ 11
+    #undef __k8__
+    #define __k8__ 1
+    #undef __INTPTR_TYPE__
+    #define __INTPTR_TYPE__ long int
+    #undef __UINT16_TYPE__
+    #define __UINT16_TYPE__ short unsigned int
+    #undef __WCHAR_TYPE__
+    #define __WCHAR_TYPE__ int
+    #undef __pic__
+    #define __pic__ 2
+    #undef __UINTPTR_MAX__
+    #define __UINTPTR_MAX__ 0xffffffffffffffffUL
+    #undef __INT_FAST64_WIDTH__
+    #define __INT_FAST64_WIDTH__ 64
+    #undef __LDBL_HAS_INFINITY__
+    #define __LDBL_HAS_INFINITY__ 1
+    #undef __INT_FAST64_MAX__
+    #define __INT_FAST64_MAX__ 0x7fffffffffffffffL
+    #undef __FLT_NORM_MAX__
+    #define __FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F
+    #undef __FLT64X_MAX_EXP__
+    #define __FLT64X_MAX_EXP__ 16384
+    #undef __UINT_FAST64_TYPE__
+    #define __UINT_FAST64_TYPE__ long unsigned int
+    #undef __BFLT16_MIN_EXP__
+    #define __BFLT16_MIN_EXP__ (-125)
+    #undef __INT_MAX__
+    #define __INT_MAX__ 0x7fffffff
+    #undef __linux__
+    #define __linux__ 1
+    #undef __INT64_TYPE__
+    #define __INT64_TYPE__ long int
+    #undef __FLT_MAX_EXP__
+    #define __FLT_MAX_EXP__ 128
+    #undef __ORDER_BIG_ENDIAN__
+    #define __ORDER_BIG_ENDIAN__ 4321
+    #undef __DBL_MANT_DIG__
+    #define __DBL_MANT_DIG__ 53
+    #undef __SIZEOF_FLOAT128__
+    #define __SIZEOF_FLOAT128__ 16
+    #undef __BFLT16_MANT_DIG__
+    #define __BFLT16_MANT_DIG__ 8
+    #undef __DEC64_MIN__
+    #define __DEC64_MIN__ 1E-383DD
+    #undef __WINT_TYPE__
+    #define __WINT_TYPE__ unsigned int
+    #undef __UINT_LEAST32_TYPE__
+    #define __UINT_LEAST32_TYPE__ unsigned int
+    #undef __SIZEOF_SHORT__
+    #define __SIZEOF_SHORT__ 2
+    #undef __FLT32_NORM_MAX__
+    #define __FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32
+    #undef __SSE__
+    #define __SSE__ 1
+    #undef __LDBL_MIN_EXP__
+    #define __LDBL_MIN_EXP__ (-16381)
+    #undef __FLT64_MAX__
+    #define __FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64
+    #undef __amd64__
+    #define __amd64__ 1
+    #undef __WINT_WIDTH__
+    #define __WINT_WIDTH__ 32
+    #undef __INT_LEAST8_MAX__
+    #define __INT_LEAST8_MAX__ 0x7f
+    #undef __INT_LEAST64_WIDTH__
+    #define __INT_LEAST64_WIDTH__ 64
+    #undef __FLT32X_MAX_10_EXP__
+    #define __FLT32X_MAX_10_EXP__ 308
+    #undef __SIZEOF_INT128__
+    #define __SIZEOF_INT128__ 16
+    #undef __FLT16_MIN__
+    #define __FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16
+    #undef __FLT64X_IS_IEC_60559__
+    #define __FLT64X_IS_IEC_60559__ 1
+    #undef __LDBL_MAX_10_EXP__
+    #define __LDBL_MAX_10_EXP__ 4932
+    #undef __ATOMIC_RELAXED
+    #define __ATOMIC_RELAXED 0
+    #undef __DBL_EPSILON__
+    #define __DBL_EPSILON__ ((double)2.22044604925031308084726333618164062e-16L)
+    #undef __INT_LEAST32_TYPE__
+    #define __INT_LEAST32_TYPE__ int
+    #undef _LP64
+    #define _LP64 1
+    #undef __UINT8_C
+    #define __UINT8_C(c) c
+    #undef __FLT64_MAX_EXP__
+    #define __FLT64_MAX_EXP__ 1024
+    #undef __SIZEOF_WCHAR_T__
+    #define __SIZEOF_WCHAR_T__ 4
+    #undef __UINT64_TYPE__
+    #define __UINT64_TYPE__ long unsigned int
+    #undef __GNUC_PATCHLEVEL__
+    #define __GNUC_PATCHLEVEL__ 1
+    #undef __FLT128_NORM_MAX__
+    #define __FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128
+    #undef __FLT64_NORM_MAX__
+    #define __FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64
+    #undef __FLT128_HAS_QUIET_NAN__
+    #define __FLT128_HAS_QUIET_NAN__ 1
+    #undef __INTMAX_MAX__
+    #define __INTMAX_MAX__ 0x7fffffffffffffffL
+    #undef __INT_FAST8_TYPE__
+    #define __INT_FAST8_TYPE__ signed char
+    #undef __FLT64X_MIN__
+    #define __FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x
+    #undef __GNUC_STDC_INLINE__
+    #define __GNUC_STDC_INLINE__ 1
+    #undef __FLT64_HAS_DENORM__
+    #define __FLT64_HAS_DENORM__ 1
+    #undef __FLT32_EPSILON__
+    #define __FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32
+    #undef __FLT16_HAS_DENORM__
+    #define __FLT16_HAS_DENORM__ 1
+    #undef __DBL_DECIMAL_DIG__
+    #define __DBL_DECIMAL_DIG__ 17
+    #undef __INT_FAST8_WIDTH__
+    #define __INT_FAST8_WIDTH__ 8
+    #undef __FXSR__
+    #define __FXSR__ 1
+    #undef __FLT32X_MAX__
+    #define __FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x
+    #undef __DBL_NORM_MAX__
+    #define __DBL_NORM_MAX__ ((double)1.79769313486231570814527423731704357e+308L)
+    #undef __BYTE_ORDER__
+    #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+    #undef __INTMAX_WIDTH__
+    #define __INTMAX_WIDTH__ 64
+    #undef __FLT32_DIG__
+    #define __FLT32_DIG__ 6
+    #undef __UINT32_C
+    #define __UINT32_C(c) c ## U
+    #undef __FLT_DENORM_MIN__
+    #define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F
+    #undef __INT8_MAX__
+    #define __INT8_MAX__ 0x7f
+    #undef __LONG_WIDTH__
+    #define __LONG_WIDTH__ 64
+    #undef __DBL_MIN__
+    #define __DBL_MIN__ ((double)2.22507385850720138309023271733240406e-308L)
+    #undef __PIC__
+    #define __PIC__ 2
+    #undef __INT32_MAX__
+    #define __INT32_MAX__ 0x7fffffff
+    #undef __UINT_FAST32_TYPE__
+    #define __UINT_FAST32_TYPE__ long unsigned int
+    #undef __FLT32X_NORM_MAX__
+    #define __FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x
+    #undef __CHAR32_TYPE__
+    #define __CHAR32_TYPE__ unsigned int
+    #undef __FLT_MAX__
+    #define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F
+    #undef __SSE2__
+    #define __SSE2__ 1
+    #undef __INT32_TYPE__
+    #define __INT32_TYPE__ int
+    #undef __SIZEOF_DOUBLE__
+    #define __SIZEOF_DOUBLE__ 8
+    #undef __FLT_MIN_10_EXP__
+    #define __FLT_MIN_10_EXP__ (-37)
+    #undef __FLT64_MIN__
+    #define __FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64
+    #undef __INT_LEAST32_WIDTH__
+    #define __INT_LEAST32_WIDTH__ 32
+    #undef __INTMAX_TYPE__
+    #define __INTMAX_TYPE__ long int
+    #undef __FLT32X_HAS_QUIET_NAN__
+    #define __FLT32X_HAS_QUIET_NAN__ 1
+    #undef __ATOMIC_CONSUME
+    #define __ATOMIC_CONSUME 1
+    #undef __GNUC_MINOR__
+    #define __GNUC_MINOR__ 1
+    #undef __UINTMAX_MAX__
+    #define __UINTMAX_MAX__ 0xffffffffffffffffUL
+    #undef __PIE__
+    #define __PIE__ 2
+    #undef __FLT32X_DENORM_MIN__
+    #define __FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x
+    #undef __DBL_MAX_10_EXP__
+    #define __DBL_MAX_10_EXP__ 308
+    #undef __LDBL_DENORM_MIN__
+    #define __LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L
+    #undef __INT16_C
+    #define __INT16_C(c) c
+    #undef __PTRDIFF_TYPE__
+    #define __PTRDIFF_TYPE__ long int
+    #undef __FLT32X_MIN_10_EXP__
+    #define __FLT32X_MIN_10_EXP__ (-307)
+    #undef __UINTPTR_TYPE__
+    #define __UINTPTR_TYPE__ long unsigned int
+    #undef __DEC64_SUBNORMAL_MIN__
+    #define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
+    #undef __DEC128_MANT_DIG__
+    #define __DEC128_MANT_DIG__ 34
+    #undef __LDBL_MIN_10_EXP__
+    #define __LDBL_MIN_10_EXP__ (-4931)
+    #undef __SIZEOF_LONG_LONG__
+    #define __SIZEOF_LONG_LONG__ 8
+    #undef __FLT128_DECIMAL_DIG__
+    #define __FLT128_DECIMAL_DIG__ 36
+    #undef __FLT32_HAS_QUIET_NAN__
+    #define __FLT32_HAS_QUIET_NAN__ 1
+    #undef __FLT_DECIMAL_DIG__
+    #define __FLT_DECIMAL_DIG__ 9
+    #undef __UINT_FAST16_MAX__
+    #define __UINT_FAST16_MAX__ 0xffffffffffffffffUL
+    #undef __LDBL_NORM_MAX__
+    #define __LDBL_NORM_MAX__ 1.18973149535723176502126385303097021e+4932L
+    #undef __SIZE_MAX__
+    #define __SIZE_MAX__ 0xffffffffffffffffUL
+    #undef __UINT_FAST8_TYPE__
+    #define __UINT_FAST8_TYPE__ unsigned char
+    #undef __ATOMIC_ACQ_REL
+    #define __ATOMIC_ACQ_REL 4
+    #undef __ATOMIC_RELEASE
+    #define __ATOMIC_RELEASE 3
+eof: (-1)
+errno:
+    e2big: '7'
+    eacces: '13'
+    eaddrinuse: '98'
+    eaddrnotavail: '99'
+    eafnosupport: '97'
+    eagain: '11'
+    ealready: '114'
+    ebade: '52'
+    ebadf: '9'
+    ebadfd: '77'
+    ebadmsg: '74'
+    ebadr: '53'
+    ebadrqc: '56'
+    ebadslt: '57'
+    ebusy: '16'
+    ecanceled: '125'
+    echild: '10'
+    echrng: '44'
+    ecomm: '70'
+    econnaborted: '103'
+    econnrefused: '111'
+    econnreset: '104'
+    edeadlk: '35'
+    edeadlock: '35'
+    edestaddrreq: '89'
+    edom: '33'
+    edquot: '122'
+    eexist: '17'
+    efault: '14'
+    efbig: '27'
+    ehostdown: '112'
+    ehostunreach: '113'
+    eidrm: '43'
+    eilseq: '84'
+    einprogress: '115'
+    eintr: '4'
+    einval: '22'
+    eio: '5'
+    eisconn: '106'
+    eisdir: '21'
+    eisnam: '120'
+    ekeyexpired: '127'
+    ekeyrejected: '129'
+    ekeyrevoked: '128'
+    el2hlt: '51'
+    el2nsync: '45'
+    el3hlt: '46'
+    el3rst: '47'
+    elibacc: '79'
+    elibbad: '80'
+    elibexec: '83'
+    elibmax: '82'
+    elibscn: '81'
+    eloop: '40'
+    emediumtype: '124'
+    emfile: '24'
+    emlink: '31'
+    emsgsize: '90'
+    emultihop: '72'
+    enametoolong: '36'
+    enetdown: '100'
+    enetreset: '102'
+    enetunreach: '101'
+    enfile: '23'
+    enobufs: '105'
+    enodata: '61'
+    enodev: '19'
+    enoent: '2'
+    enoexec: '8'
+    enokey: '126'
+    enolck: '37'
+    enolink: '67'
+    enomedium: '123'
+    enomem: '12'
+    enomsg: '42'
+    enonet: '64'
+    enopkg: '65'
+    enoprotoopt: '92'
+    enospc: '28'
+    enosr: '63'
+    enostr: '60'
+    enosys: '38'
+    enotblk: '15'
+    enotconn: '107'
+    enotdir: '20'
+    enotempty: '39'
+    enotrecoverable: '131'
+    enotsock: '88'
+    enotsup: '95'
+    enotty: '25'
+    enotuniq: '76'
+    enxio: '6'
+    eopnotsupp: '95'
+    eoverflow: '75'
+    eownerdead: '130'
+    eperm: '1'
+    epfnosupport: '96'
+    epipe: '32'
+    eproto: '71'
+    eprotonosupport: '93'
+    eprototype: '91'
+    erange: '34'
+    eremchg: '78'
+    eremote: '66'
+    eremoteio: '121'
+    erestart: '85'
+    erofs: '30'
+    eshutdown: '108'
+    esocktnosupport: '94'
+    espipe: '29'
+    esrch: '3'
+    estale: '116'
+    estrpipe: '86'
+    etime: '62'
+    etimedout: '110'
+    etxtbsy: '26'
+    euclean: '117'
+    eunatch: '49'
+    eusers: '87'
+    ewouldblock: '11'
+    exdev: '18'
+    exfull: '54'
+filename_max: '4096'
+fopen_max: '16'
+has__builtin_va_list: true
+host_name_max: '64'
+int_fast16_t: long
+int_fast32_t: long
+int_fast64_t: long
+int_fast8_t: signed char
+intptr_t: long
+l_tmpnam: '20'
+little_endian: true
+machdep_name: machdep_x86_64
+mb_cur_max: ((size_t) 16 )
+nsig: (64 + 1)
+path_max: '4096'
+posix_version: 200809L
+ptrdiff_t: long
+rand_max: '2147483647'
+sig_atomic_t: int
+size_t: unsigned long
+sizeof_double: 8
+sizeof_float: 4
+sizeof_fun: -1
+sizeof_int: 4
+sizeof_long: 8
+sizeof_longdouble: 16
+sizeof_longlong: 8
+sizeof_ptr: 8
+sizeof_short: 2
+sizeof_void: -1
+ssize_t: long
+time_t: long
+tmp_max: '238328'
+tty_name_max: '32'
+uint_fast16_t: unsigned long
+uint_fast32_t: unsigned long
+uint_fast64_t: unsigned long
+uint_fast8_t: unsigned char
+uintptr_t: unsigned long
+version: gcc (GCC) 13.1.1 20230429
+wchar_t: int
+weof: (0xffffffffu)
+wint_t: unsigned int
+wordsize: '64'
diff --git a/share/machdeps/make_machdep/.gitignore b/share/machdeps/make_machdep/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..5761abcfdf0c26a75374c945dfe366eaeee04285
--- /dev/null
+++ b/share/machdeps/make_machdep/.gitignore
@@ -0,0 +1 @@
+*.o
diff --git a/share/machdeps/make_machdep/alignof_aligned.c b/share/machdeps/make_machdep/alignof_aligned.c
new file mode 100644
index 0000000000000000000000000000000000000000..8d37ca3c5f94b8f0343dc16b4499710dcd023172
--- /dev/null
+++ b/share/machdeps/make_machdep/alignof_aligned.c
@@ -0,0 +1,42 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+
+typedef char array[1] __attribute__((__aligned__));
+
+_Static_assert(ALIGNOF(array)!=1, "alignof_aligned is 1");
+_Static_assert(ALIGNOF(array)!=2, "alignof_aligned is 2");
+_Static_assert(ALIGNOF(array)!=3, "alignof_aligned is 3");
+_Static_assert(ALIGNOF(array)!=4, "alignof_aligned is 4");
+_Static_assert(ALIGNOF(array)!=5, "alignof_aligned is 5");
+_Static_assert(ALIGNOF(array)!=6, "alignof_aligned is 6");
+_Static_assert(ALIGNOF(array)!=7, "alignof_aligned is 7");
+_Static_assert(ALIGNOF(array)!=8, "alignof_aligned is 8");
+_Static_assert(ALIGNOF(array)!=9, "alignof_aligned is 9");
+_Static_assert(ALIGNOF(array)!=10, "alignof_aligned is 10");
+_Static_assert(ALIGNOF(array)!=11, "alignof_aligned is 11");
+_Static_assert(ALIGNOF(array)!=12, "alignof_aligned is 12");
+_Static_assert(ALIGNOF(array)!=13, "alignof_aligned is 13");
+_Static_assert(ALIGNOF(array)!=14, "alignof_aligned is 14");
+_Static_assert(ALIGNOF(array)!=15, "alignof_aligned is 15");
+_Static_assert(ALIGNOF(array)!=16, "alignof_aligned is 16");
diff --git a/share/machdeps/make_machdep/alignof_double.c b/share/machdeps/make_machdep/alignof_double.c
new file mode 100644
index 0000000000000000000000000000000000000000..3ad3c9526be103cbb5f4ce11a6ae5d7b83174d13
--- /dev/null
+++ b/share/machdeps/make_machdep/alignof_double.c
@@ -0,0 +1,32 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+
+_Static_assert(ALIGNOF(double) != 1, "alignof_double is 1");
+_Static_assert(ALIGNOF(double) != 2, "alignof_double is 2");
+_Static_assert(ALIGNOF(double) != 3, "alignof_double is 3");
+_Static_assert(ALIGNOF(double) != 4, "alignof_double is 4");
+_Static_assert(ALIGNOF(double) != 5, "alignof_double is 5");
+_Static_assert(ALIGNOF(double) != 6, "alignof_double is 6");
+_Static_assert(ALIGNOF(double) != 7, "alignof_double is 7");
+_Static_assert(ALIGNOF(double) != 8, "alignof_double is 8");
diff --git a/share/machdeps/make_machdep/alignof_float.c b/share/machdeps/make_machdep/alignof_float.c
new file mode 100644
index 0000000000000000000000000000000000000000..2bbb0bf8967db1baa1a3889a27041d123d5f4e7f
--- /dev/null
+++ b/share/machdeps/make_machdep/alignof_float.c
@@ -0,0 +1,32 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+
+_Static_assert(ALIGNOF(float) != 1, "alignof_float is 1");
+_Static_assert(ALIGNOF(float) != 2, "alignof_float is 2");
+_Static_assert(ALIGNOF(float) != 3, "alignof_float is 3");
+_Static_assert(ALIGNOF(float) != 4, "alignof_float is 4");
+_Static_assert(ALIGNOF(float) != 5, "alignof_float is 5");
+_Static_assert(ALIGNOF(float) != 6, "alignof_float is 6");
+_Static_assert(ALIGNOF(float) != 7, "alignof_float is 7");
+_Static_assert(ALIGNOF(float) != 8, "alignof_float is 8");
diff --git a/share/machdeps/make_machdep/alignof_fun.c b/share/machdeps/make_machdep/alignof_fun.c
new file mode 100644
index 0000000000000000000000000000000000000000..0d26a6404280d6eecfe27e0f8eba5c758df8a688
--- /dev/null
+++ b/share/machdeps/make_machdep/alignof_fun.c
@@ -0,0 +1,32 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+
+_Static_assert(ALIGNOF(void()) != 1, "alignof_fun is 1");
+_Static_assert(ALIGNOF(void()) != 2, "alignof_fun is 2");
+_Static_assert(ALIGNOF(void()) != 3, "alignof_fun is 3");
+_Static_assert(ALIGNOF(void()) != 4, "alignof_fun is 4");
+_Static_assert(ALIGNOF(void()) != 5, "alignof_fun is 5");
+_Static_assert(ALIGNOF(void()) != 6, "alignof_fun is 6");
+_Static_assert(ALIGNOF(void()) != 7, "alignof_fun is 7");
+_Static_assert(ALIGNOF(void()) != 8, "alignof_fun is 8");
diff --git a/share/machdeps/make_machdep/alignof_int.c b/share/machdeps/make_machdep/alignof_int.c
new file mode 100644
index 0000000000000000000000000000000000000000..a83f429cd061be487e130f0fc69330cdb8e563a5
--- /dev/null
+++ b/share/machdeps/make_machdep/alignof_int.c
@@ -0,0 +1,31 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+_Static_assert(ALIGNOF(int) != 1, "alignof_int is 1");
+_Static_assert(ALIGNOF(int) != 2, "alignof_int is 2");
+_Static_assert(ALIGNOF(int) != 3, "alignof_int is 3");
+_Static_assert(ALIGNOF(int) != 4, "alignof_int is 4");
+_Static_assert(ALIGNOF(int) != 5, "alignof_int is 5");
+_Static_assert(ALIGNOF(int) != 6, "alignof_int is 6");
+_Static_assert(ALIGNOF(int) != 7, "alignof_int is 7");
+_Static_assert(ALIGNOF(int) != 8, "alignof_int is 8");
diff --git a/share/machdeps/make_machdep/alignof_long.c b/share/machdeps/make_machdep/alignof_long.c
new file mode 100644
index 0000000000000000000000000000000000000000..f34ec3ca89f349404fbe181edf9c90adc78fb85f
--- /dev/null
+++ b/share/machdeps/make_machdep/alignof_long.c
@@ -0,0 +1,31 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+_Static_assert(ALIGNOF(long) != 1, "alignof_long is 1");
+_Static_assert(ALIGNOF(long) != 2, "alignof_long is 2");
+_Static_assert(ALIGNOF(long) != 3, "alignof_long is 3");
+_Static_assert(ALIGNOF(long) != 4, "alignof_long is 4");
+_Static_assert(ALIGNOF(long) != 5, "alignof_long is 5");
+_Static_assert(ALIGNOF(long) != 6, "alignof_long is 6");
+_Static_assert(ALIGNOF(long) != 7, "alignof_long is 7");
+_Static_assert(ALIGNOF(long) != 8, "alignof_long is 8");
diff --git a/share/machdeps/make_machdep/alignof_longdouble.c b/share/machdeps/make_machdep/alignof_longdouble.c
new file mode 100644
index 0000000000000000000000000000000000000000..0cd52668fe54cad32a0b0d26429259927365b5e7
--- /dev/null
+++ b/share/machdeps/make_machdep/alignof_longdouble.c
@@ -0,0 +1,40 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+
+_Static_assert(ALIGNOF(long double) != 1, "alignof_longdouble is 1");
+_Static_assert(ALIGNOF(long double) != 2, "alignof_longdouble is 2");
+_Static_assert(ALIGNOF(long double) != 3, "alignof_longdouble is 3");
+_Static_assert(ALIGNOF(long double) != 4, "alignof_longdouble is 4");
+_Static_assert(ALIGNOF(long double) != 5, "alignof_longdouble is 5");
+_Static_assert(ALIGNOF(long double) != 6, "alignof_longdouble is 6");
+_Static_assert(ALIGNOF(long double) != 7, "alignof_longdouble is 7");
+_Static_assert(ALIGNOF(long double) != 8, "alignof_longdouble is 8");
+_Static_assert(ALIGNOF(long double) != 9, "alignof_longdouble is 9");
+_Static_assert(ALIGNOF(long double) != 10, "alignof_longdouble is 10");
+_Static_assert(ALIGNOF(long double) != 11, "alignof_longdouble is 11");
+_Static_assert(ALIGNOF(long double) != 12, "alignof_longdouble is 12");
+_Static_assert(ALIGNOF(long double) != 13, "alignof_longdouble is 13");
+_Static_assert(ALIGNOF(long double) != 14, "alignof_longdouble is 14");
+_Static_assert(ALIGNOF(long double) != 15, "alignof_longdouble is 15");
+_Static_assert(ALIGNOF(long double) != 16, "alignof_longdouble is 16");
diff --git a/share/machdeps/make_machdep/alignof_longlong.c b/share/machdeps/make_machdep/alignof_longlong.c
new file mode 100644
index 0000000000000000000000000000000000000000..222eba81362a4089b7af59a5ff0891817be497be
--- /dev/null
+++ b/share/machdeps/make_machdep/alignof_longlong.c
@@ -0,0 +1,31 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+_Static_assert(ALIGNOF(long long) != 1, "alignof_longlong is 1");
+_Static_assert(ALIGNOF(long long) != 2, "alignof_longlong is 2");
+_Static_assert(ALIGNOF(long long) != 3, "alignof_longlong is 3");
+_Static_assert(ALIGNOF(long long) != 4, "alignof_longlong is 4");
+_Static_assert(ALIGNOF(long long) != 5, "alignof_longlong is 5");
+_Static_assert(ALIGNOF(long long) != 6, "alignof_longlong is 6");
+_Static_assert(ALIGNOF(long long) != 7, "alignof_longlong is 7");
+_Static_assert(ALIGNOF(long long) != 8, "alignof_longlong is 8");
diff --git a/share/machdeps/make_machdep/alignof_ptr.c b/share/machdeps/make_machdep/alignof_ptr.c
new file mode 100644
index 0000000000000000000000000000000000000000..babe1cd560d7277132648ee2a6396bd2910768a9
--- /dev/null
+++ b/share/machdeps/make_machdep/alignof_ptr.c
@@ -0,0 +1,32 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+
+_Static_assert(ALIGNOF(void *) != 1, "alignof_ptr is 1");
+_Static_assert(ALIGNOF(void *) != 2, "alignof_ptr is 2");
+_Static_assert(ALIGNOF(void *) != 3, "alignof_ptr is 3");
+_Static_assert(ALIGNOF(void *) != 4, "alignof_ptr is 4");
+_Static_assert(ALIGNOF(void *) != 5, "alignof_ptr is 5");
+_Static_assert(ALIGNOF(void *) != 6, "alignof_ptr is 6");
+_Static_assert(ALIGNOF(void *) != 7, "alignof_ptr is 7");
+_Static_assert(ALIGNOF(void *) != 8, "alignof_ptr is 8");
diff --git a/share/machdeps/make_machdep/alignof_short.c b/share/machdeps/make_machdep/alignof_short.c
new file mode 100644
index 0000000000000000000000000000000000000000..7e1c66cfa417d6a94081d640443911add7c316fa
--- /dev/null
+++ b/share/machdeps/make_machdep/alignof_short.c
@@ -0,0 +1,31 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+_Static_assert(ALIGNOF(short) != 1, "alignof_short is 1");
+_Static_assert(ALIGNOF(short) != 2, "alignof_short is 2");
+_Static_assert(ALIGNOF(short) != 3, "alignof_short is 3");
+_Static_assert(ALIGNOF(short) != 4, "alignof_short is 4");
+_Static_assert(ALIGNOF(short) != 5, "alignof_short is 5");
+_Static_assert(ALIGNOF(short) != 6, "alignof_short is 6");
+_Static_assert(ALIGNOF(short) != 7, "alignof_short is 7");
+_Static_assert(ALIGNOF(short) != 8, "alignof_short is 8");
diff --git a/share/machdeps/make_machdep/alignof_str.c b/share/machdeps/make_machdep/alignof_str.c
new file mode 100644
index 0000000000000000000000000000000000000000..51ba68521cd21c26e24fcd5f362f4e4c1cb2cb5b
--- /dev/null
+++ b/share/machdeps/make_machdep/alignof_str.c
@@ -0,0 +1,32 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+
+_Static_assert(ALIGNOF("test string") != 1, "alignof_str is 1");
+_Static_assert(ALIGNOF("test string") != 2, "alignof_str is 2");
+_Static_assert(ALIGNOF("test string") != 3, "alignof_str is 3");
+_Static_assert(ALIGNOF("test string") != 4, "alignof_str is 4");
+_Static_assert(ALIGNOF("test string") != 5, "alignof_str is 5");
+_Static_assert(ALIGNOF("test string") != 6, "alignof_str is 6");
+_Static_assert(ALIGNOF("test string") != 7, "alignof_str is 7");
+_Static_assert(ALIGNOF("test string") != 8, "alignof_str is 8");
diff --git a/share/machdeps/make_machdep/char_is_unsigned.c b/share/machdeps/make_machdep/char_is_unsigned.c
new file mode 100644
index 0000000000000000000000000000000000000000..46ad63d750231360d7f276aa2d62e04f31e5cfd5
--- /dev/null
+++ b/share/machdeps/make_machdep/char_is_unsigned.c
@@ -0,0 +1,24 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+_Static_assert((char)-1 >= 0 ? 1 : 0, "char_is_unsigned is False");
+_Static_assert((char)-1 >= 0 ? 0 : 1, "char_is_unsigned is True");
diff --git a/share/machdeps/make_machdep/const_string_literals.c b/share/machdeps/make_machdep/const_string_literals.c
new file mode 100644
index 0000000000000000000000000000000000000000..35fb4e651ec1e4c5ba3f07033d19e1085bb37137
--- /dev/null
+++ b/share/machdeps/make_machdep/const_string_literals.c
@@ -0,0 +1,23 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+char *const_string_literals = "%$#!";
diff --git a/share/machdeps/make_machdep/errno.c b/share/machdeps/make_machdep/errno.c
new file mode 100644
index 0000000000000000000000000000000000000000..a6c2829d87f7e686c129f4f7c691abc9df57d0c8
--- /dev/null
+++ b/share/machdeps/make_machdep/errno.c
@@ -0,0 +1,393 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include <errno.h>
+
+/* Mandatory */
+#ifdef EDOM
+int edom_is = EDOM;
+#endif
+#ifdef EILSEQ
+int eilseq_is = EILSEQ;
+#endif
+#ifdef ERANGE
+int erange_is = ERANGE;
+#endif
+
+/* Implementation defined by POSIX and GNU Linux */
+#ifdef E2BIG
+int e2big_is = E2BIG;
+#endif
+#ifdef EACCES
+int eacces_is = EACCES;
+#endif
+#ifdef EADDRINUSE
+int eaddrinuse_is = EADDRINUSE;
+#endif
+#ifdef EADDRNOTAVAIL
+int eaddrnotavail_is = EADDRNOTAVAIL;
+#endif
+#ifdef EAFNOSUPPORT
+int eafnosupport_is = EAFNOSUPPORT;
+#endif
+#ifdef EAGAIN
+int eagain_is = EAGAIN;
+#endif
+#ifdef EALREADY
+int ealready_is = EALREADY;
+#endif
+#ifdef EBADE
+int ebade_is = EBADE;
+#endif
+#ifdef EBADF
+int ebadf_is = EBADF;
+#endif
+#ifdef EBADFD
+int ebadfd_is = EBADFD;
+#endif
+#ifdef EBADMSG
+int ebadmsg_is = EBADMSG;
+#endif
+#ifdef EBADR
+int ebadr_is = EBADR;
+#endif
+#ifdef EBADRQC
+int ebadrqc_is = EBADRQC;
+#endif
+#ifdef EBADSLT
+int ebadslt_is = EBADSLT;
+#endif
+#ifdef EBUSY
+int ebusy_is = EBUSY;
+#endif
+#ifdef ECANCELED
+int ecanceled_is = ECANCELED;
+#endif
+#ifdef ECHILD
+int echild_is = ECHILD;
+#endif
+#ifdef ECHRNG
+int echrng_is = ECHRNG;
+#endif
+#ifdef ECOMM
+int ecomm_is = ECOMM;
+#endif
+#ifdef ECONNABORTED
+int econnaborted_is = ECONNABORTED;
+#endif
+#ifdef ECONNREFUSED
+int econnrefused_is = ECONNREFUSED;
+#endif
+#ifdef ECONNRESET
+int econnreset_is = ECONNRESET;
+#endif
+#ifdef EDEADLK
+int edeadlk_is = EDEADLK;
+#endif
+#ifdef EDEADLOCK
+int edeadlock_is = EDEADLOCK;
+#endif
+#ifdef EDESTADDRREQ
+int edestaddrreq_is = EDESTADDRREQ;
+#endif
+#ifdef EDQUOT
+int edquot_is = EDQUOT;
+#endif
+#ifdef EEXIST
+int eexist_is = EEXIST;
+#endif
+#ifdef EFAULT
+int efault_is = EFAULT;
+#endif
+#ifdef EFBIG
+int efbig_is = EFBIG;
+#endif
+#ifdef EHOSTDOWN
+int ehostdown_is = EHOSTDOWN;
+#endif
+#ifdef EHOSTUNREACH
+int ehostunreach_is = EHOSTUNREACH;
+#endif
+#ifdef EIDRM
+int eidrm_is = EIDRM;
+#endif
+#ifdef EINPROGRESS
+int einprogress_is = EINPROGRESS;
+#endif
+#ifdef EINTR
+int eintr_is = EINTR;
+#endif
+#ifdef EINVAL
+int einval_is = EINVAL;
+#endif
+#ifdef EIO
+int eio_is = EIO;
+#endif
+#ifdef EISCONN
+int eisconn_is = EISCONN;
+#endif
+#ifdef EISDIR
+int eisdir_is = EISDIR;
+#endif
+#ifdef EISNAM
+int eisnam_is = EISNAM;
+#endif
+#ifdef EKEYEXPIRED
+int ekeyexpired_is = EKEYEXPIRED;
+#endif
+#ifdef EKEYREJECTED
+int ekeyrejected_is = EKEYREJECTED;
+#endif
+#ifdef EKEYREVOKED
+int ekeyrevoked_is = EKEYREVOKED;
+#endif
+#ifdef EL2HLT
+int el2hlt_is = EL2HLT;
+#endif
+#ifdef EL2NSYNC
+int el2nsync_is = EL2NSYNC;
+#endif
+#ifdef EL3HLT
+int el3hlt_is = EL3HLT;
+#endif
+#ifdef EL3RST
+int el3rst_is = EL3RST;
+#endif
+#ifdef ELIBACC
+int elibacc_is = ELIBACC;
+#endif
+#ifdef ELIBBAD
+int elibbad_is = ELIBBAD;
+#endif
+#ifdef ELIBMAX
+int elibmax_is = ELIBMAX;
+#endif
+#ifdef ELIBSCN
+int elibscn_is = ELIBSCN;
+#endif
+#ifdef ELIBEXEC
+int elibexec_is = ELIBEXEC;
+#endif
+#ifdef ELOOP
+int eloop_is = ELOOP;
+#endif
+#ifdef EMEDIUMTYPE
+int emediumtype_is = EMEDIUMTYPE;
+#endif
+#ifdef EMFILE
+int emfile_is = EMFILE;
+#endif
+#ifdef EMLINK
+int emlink_is = EMLINK;
+#endif
+#ifdef EMSGSIZE
+int emsgsize_is = EMSGSIZE;
+#endif
+#ifdef EMULTIHOP
+int emultihop_is = EMULTIHOP;
+#endif
+#ifdef ENAMETOOLONG
+int enametoolong_is = ENAMETOOLONG;
+#endif
+#ifdef ENETDOWN
+int enetdown_is = ENETDOWN;
+#endif
+#ifdef ENETRESET
+int enetreset_is = ENETRESET;
+#endif
+#ifdef ENETUNREACH
+int enetunreach_is = ENETUNREACH;
+#endif
+#ifdef ENFILE
+int enfile_is = ENFILE;
+#endif
+#ifdef ENOBUFS
+int enobufs_is = ENOBUFS;
+#endif
+#ifdef ENODATA
+int enodata_is = ENODATA;
+#endif
+#ifdef ENODEV
+int enodev_is = ENODEV;
+#endif
+#ifdef ENOENT
+int enoent_is = ENOENT;
+#endif
+#ifdef ENOEXEC
+int enoexec_is = ENOEXEC;
+#endif
+#ifdef ENOKEY
+int enokey_is = ENOKEY;
+#endif
+#ifdef ENOLCK
+int enolck_is = ENOLCK;
+#endif
+#ifdef ENOLINK
+int enolink_is = ENOLINK;
+#endif
+#ifdef ENOMEDIUM
+int enomedium_is = ENOMEDIUM;
+#endif
+#ifdef ENOMEM
+int enomem_is = ENOMEM;
+#endif
+#ifdef ENOMSG
+int enomsg_is = ENOMSG;
+#endif
+#ifdef ENONET
+int enonet_is = ENONET;
+#endif
+#ifdef ENOPKG
+int enopkg_is = ENOPKG;
+#endif
+#ifdef ENOPROTOOPT
+int enoprotoopt_is = ENOPROTOOPT;
+#endif
+#ifdef ENOSPC
+int enospc_is = ENOSPC;
+#endif
+#ifdef ENOSR
+int enosr_is = ENOSR;
+#endif
+#ifdef ENOSTR
+int enostr_is = ENOSTR;
+#endif
+#ifdef ENOSYS
+int enosys_is = ENOSYS;
+#endif
+#ifdef ENOTBLK
+int enotblk_is = ENOTBLK;
+#endif
+#ifdef ENOTCONN
+int enotconn_is = ENOTCONN;
+#endif
+#ifdef ENOTDIR
+int enotdir_is = ENOTDIR;
+#endif
+#ifdef ENOTEMPTY
+int enotempty_is = ENOTEMPTY;
+#endif
+#ifdef ENOTRECOVERABLE
+int enotrecoverable_is = ENOTRECOVERABLE;
+#endif
+#ifdef ENOTSOCK
+int enotsock_is = ENOTSOCK;
+#endif
+#ifdef ENOTSUP
+int enotsup_is = ENOTSUP;
+#endif
+#ifdef ENOTTY
+int enotty_is = ENOTTY;
+#endif
+#ifdef ENOTUNIQ
+int enotuniq_is = ENOTUNIQ;
+#endif
+#ifdef ENXIO
+int enxio_is = ENXIO;
+#endif
+#ifdef EOPNOTSUPP
+int eopnotsupp_is = EOPNOTSUPP;
+#endif
+#ifdef EOVERFLOW
+int eoverflow_is = EOVERFLOW;
+#endif
+#ifdef EOWNERDEAD
+int eownerdead_is = EOWNERDEAD;
+#endif
+#ifdef EPERM
+int eperm_is = EPERM;
+#endif
+#ifdef EPFNOSUPPORT
+int epfnosupport_is = EPFNOSUPPORT;
+#endif
+#ifdef EPIPE
+int epipe_is = EPIPE;
+#endif
+#ifdef EPROTO
+int eproto_is = EPROTO;
+#endif
+#ifdef EPROTONOSUPPORT
+int eprotonosupport_is = EPROTONOSUPPORT;
+#endif
+#ifdef EPROTOTYPE
+int eprototype_is = EPROTOTYPE;
+#endif
+#ifdef EREMCHG
+int eremchg_is = EREMCHG;
+#endif
+#ifdef EREMOTE
+int eremote_is = EREMOTE;
+#endif
+#ifdef EREMOTEIO
+int eremoteio_is = EREMOTEIO;
+#endif
+#ifdef ERESTART
+int erestart_is = ERESTART;
+#endif
+#ifdef EROFS
+int erofs_is = EROFS;
+#endif
+#ifdef ESHUTDOWN
+int eshutdown_is = ESHUTDOWN;
+#endif
+#ifdef ESPIPE
+int espipe_is = ESPIPE;
+#endif
+#ifdef ESOCKTNOSUPPORT
+int esocktnosupport_is = ESOCKTNOSUPPORT;
+#endif
+#ifdef ESRCH
+int esrch_is = ESRCH;
+#endif
+#ifdef ESTALE
+int estale_is = ESTALE;
+#endif
+#ifdef ESTRPIPE
+int estrpipe_is = ESTRPIPE;
+#endif
+#ifdef ETIME
+int etime_is = ETIME;
+#endif
+#ifdef ETIMEDOUT
+int etimedout_is = ETIMEDOUT;
+#endif
+#ifdef ETXTBSY
+int etxtbsy_is = ETXTBSY;
+#endif
+#ifdef EUCLEAN
+int euclean_is = EUCLEAN;
+#endif
+#ifdef EUNATCH
+int eunatch_is = EUNATCH;
+#endif
+#ifdef EUSERS
+int eusers_is = EUSERS;
+#endif
+#ifdef EWOULDBLOCK
+int ewouldblock_is = EWOULDBLOCK;
+#endif
+#ifdef EXDEV
+int exdev_is = EXDEV;
+#endif
+#ifdef EXFULL
+int exfull_is = EXFULL;
+#endif
diff --git a/share/machdeps/make_machdep/has__builtin_va_list.c b/share/machdeps/make_machdep/has__builtin_va_list.c
new file mode 100644
index 0000000000000000000000000000000000000000..4f2420598eca140e508b6f6259185edadea87388
--- /dev/null
+++ b/share/machdeps/make_machdep/has__builtin_va_list.c
@@ -0,0 +1,24 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+/* If this compiles, we assume the compiler has __builtin_va_list. */
+__builtin_va_list l = {0};
diff --git a/share/machdeps/make_machdep/int_fast16_t.c b/share/machdeps/make_machdep/int_fast16_t.c
new file mode 100644
index 0000000000000000000000000000000000000000..77a451ab2da7c881ce840e8e679aabb89f874444
--- /dev/null
+++ b/share/machdeps/make_machdep/int_fast16_t.c
@@ -0,0 +1,31 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+#include <stdint.h>
+#define TEST_TYPE int_fast16_t
+
+TEST_TYPE_IS(signed char);
+TEST_TYPE_IS(short);
+TEST_TYPE_IS(int);
+TEST_TYPE_IS(long);
+TEST_TYPE_IS(long long);
diff --git a/share/machdeps/make_machdep/int_fast32_t.c b/share/machdeps/make_machdep/int_fast32_t.c
new file mode 100644
index 0000000000000000000000000000000000000000..fbbfee3a162b972732022954b08a3bd57bcee3ba
--- /dev/null
+++ b/share/machdeps/make_machdep/int_fast32_t.c
@@ -0,0 +1,31 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+#include <stdint.h>
+#define TEST_TYPE int_fast32_t
+
+TEST_TYPE_IS(signed char);
+TEST_TYPE_IS(short);
+TEST_TYPE_IS(int);
+TEST_TYPE_IS(long);
+TEST_TYPE_IS(long long);
diff --git a/share/machdeps/make_machdep/int_fast64_t.c b/share/machdeps/make_machdep/int_fast64_t.c
new file mode 100644
index 0000000000000000000000000000000000000000..43b3ce1797a450aa87a14a06646c4a0eb50cbd29
--- /dev/null
+++ b/share/machdeps/make_machdep/int_fast64_t.c
@@ -0,0 +1,31 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+#include <stdint.h>
+#define TEST_TYPE int_fast64_t
+
+TEST_TYPE_IS(signed char);
+TEST_TYPE_IS(short);
+TEST_TYPE_IS(int);
+TEST_TYPE_IS(long);
+TEST_TYPE_IS(long long);
diff --git a/share/machdeps/make_machdep/int_fast8_t.c b/share/machdeps/make_machdep/int_fast8_t.c
new file mode 100644
index 0000000000000000000000000000000000000000..6d572f914dee75cba1307076181000cea8495ca1
--- /dev/null
+++ b/share/machdeps/make_machdep/int_fast8_t.c
@@ -0,0 +1,31 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+#include <stdint.h>
+#define TEST_TYPE int_fast8_t
+
+TEST_TYPE_IS(signed char);
+TEST_TYPE_IS(short);
+TEST_TYPE_IS(int);
+TEST_TYPE_IS(long);
+TEST_TYPE_IS(long long);
diff --git a/share/machdeps/make_machdep/intptr_t.c b/share/machdeps/make_machdep/intptr_t.c
new file mode 100644
index 0000000000000000000000000000000000000000..ec1f36e633d82dd9609870cfc937498a15cf661c
--- /dev/null
+++ b/share/machdeps/make_machdep/intptr_t.c
@@ -0,0 +1,29 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+#include <stdint.h>
+#define TEST_TYPE intptr_t
+
+TEST_TYPE_IS(int);
+TEST_TYPE_IS(long);
+TEST_TYPE_IS(long long);
diff --git a/share/machdeps/make_machdep/limits_macros.c b/share/machdeps/make_machdep/limits_macros.c
new file mode 100644
index 0000000000000000000000000000000000000000..e6d7abd64c4d6b24b10dfc605bd47da2704f9009
--- /dev/null
+++ b/share/machdeps/make_machdep/limits_macros.c
@@ -0,0 +1,35 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include <limits.h>
+
+#if defined(PATH_MAX)
+int path_max_is = PATH_MAX;
+#endif
+
+#if defined(TTY_NAME_MAX)
+int tty_name_max_is = TTY_NAME_MAX;
+#endif
+
+#if defined(HOST_NAME_MAX)
+int host_name_max_is = HOST_NAME_MAX;
+#endif
diff --git a/share/machdeps/make_machdep/little_endian.c b/share/machdeps/make_machdep/little_endian.c
new file mode 100644
index 0000000000000000000000000000000000000000..2e1404de7a3f0595bab45fd9cdb20dbbbe91ba98
--- /dev/null
+++ b/share/machdeps/make_machdep/little_endian.c
@@ -0,0 +1,33 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#if defined(__BYTE_ORDER__)
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+_Static_assert(0, "little_endian is False");
+#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+_Static_assert(0, "little_endian is True");
+#else
+#error Unexpected __BYTE_ORDER__
+#endif
+#else
+#error __BYTE_ORDER__ undefined
+#endif
diff --git a/share/machdeps/make_machdep/make_machdep.py b/share/machdeps/make_machdep/make_machdep.py
new file mode 100755
index 0000000000000000000000000000000000000000..bd0b6cefa82eeebfdbf575326681d26122018c34
--- /dev/null
+++ b/share/machdeps/make_machdep/make_machdep.py
@@ -0,0 +1,438 @@
+#!/usr/bin/env python
+##########################################################################
+#                                                                        #
+#  This file is part of Frama-C.                                         #
+#                                                                        #
+#  Copyright (C) 2007-2023                                               #
+#    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).            #
+#                                                                        #
+##########################################################################
+
+"""
+Produces a machdep.yaml file for a given architecture.
+
+Prerequisites:
+
+- A C11-compatible (cross-)compiler (with support for _Generic),
+- A (cross-)compiler supporting _Static_assert
+- A (cross-)compiler supporting _Alignof or alignof
+
+This script tries to compile several source files to extract the
+information we need in terms of sizeof, alignof and representation
+of the various types defined by the standard (e.g. size_t, wchar_t, ...)
+
+In case some values are not identified, the YAML format can be edited
+by hand afterwards.
+"""
+
+import argparse
+from pathlib import Path
+import re
+import subprocess
+import sys
+import logging
+import yaml
+from yaml.representer import Representer
+
+my_path = Path(sys.argv[0]).parent
+
+logging.basicConfig(format="%(levelname)s: %(message)s")
+
+parser = argparse.ArgumentParser(prog="make_machdep")
+parser.add_argument("-v", "--verbose", action="store_true")
+parser.add_argument("-o", type=argparse.FileType("w"), dest="dest_file")
+parser.add_argument("--compiler", default="cc", help="which compiler to use; default is 'cc'")
+parser.add_argument(
+    "--compiler-version",
+    default="--version",
+    help="option to pass to the compiler to obtain its version; default is --version",
+)
+
+parser.add_argument(
+    "--from-file",
+    help="reads compiler and arch flags from existing yaml file. Use -i to update it in place",
+)
+parser.add_argument(
+    "-i",
+    "--in-place",
+    action="store_true",
+    help="when reading compiler config from yaml, update the file in place. unused otherwise",
+)
+
+parser.add_argument(
+    "--cpp-arch-flags",
+    nargs="+",
+    action="extend",
+    help="architecture-specific flags needed for preprocessing, e.g. '-m32'",
+)
+parser.add_argument(
+    "--compiler-flags",
+    nargs="+",
+    action="extend",
+    type=str,
+    help="flags to be given to the compiler (other than those set by --cpp-arch-flags); default is '-c'",
+)
+parser.add_argument(
+    "--check",
+    action="store_true",
+    help="checks that the generated machdep is conforming to the schema",
+)
+parser.add_argument(
+    "--check-only",
+    action="store_true",
+    help="must be used in conjunction with --from-file to check that the provided input file is conforming to the schema",
+)
+
+args, other_args = parser.parse_known_args()
+
+if not args.compiler_flags:
+    args.compiler_flags = ["-c"]
+
+if not args.cpp_arch_flags:
+    args.cpp_arch_flags = []
+
+
+def make_schema():
+    schema_filename = my_path.parent / "machdep-schema.yaml"
+    with open(schema_filename, "r") as schema:
+        return yaml.safe_load(schema)
+
+
+schema = make_schema()
+
+
+def check_machdep(machdep):
+    try:
+        from jsonschema import validate, ValidationError
+
+        validate(machdep, schema)
+        return True
+    except ImportError:
+        logging.warning("jsonschema is not available: no validation will be performed")
+        return True
+    except ValidationError:
+        logging.warning("machdep object is not conforming to machdep schema")
+        return False
+
+
+if args.from_file:
+    orig_file = open(args.from_file, "r")
+    orig_machdep = yaml.safe_load(orig_file)
+    orig_file.close()
+    if args.check_only:
+        if check_machdep(orig_machdep):
+            sys.exit(0)
+        else:
+            sys.exit(1)
+    if not "compiler" in orig_machdep or not "cpp_arch_flags" in orig_machdep:
+        raise Exception("Missing fields in yaml file")
+    args.compiler = orig_machdep["compiler"]
+    if isinstance(orig_machdep["cpp_arch_flags"], list):
+        args.cpp_arch_flags = orig_machdep["cpp_arch_flags"]
+    else:  # old version of the schema used a single string
+        args.cpp_arch_flags = orig_machdep["cpp_arch_flags"].split()
+
+
+def print_machdep(machdep):
+    if args.from_file and args.in_place:
+        args.dest_file = open(args.from_file, "w")
+    elif args.dest_file is None:
+        args.dest_file = sys.stdout
+    yaml.dump(machdep, args.dest_file, indent=4, sort_keys=True)
+
+
+def default_value(typ):
+    if typ == "integer":
+        return -1
+    if typ == "boolean":
+        return False
+    if typ == "string":
+        return ""
+    if typ == "list":
+        return {}
+    logging.warning(f"Unexpected type {typ} in YAML schema")
+    return None
+
+
+def make_machdep():
+    machdep = {}
+    for key in schema:
+        machdep[key] = None
+    return machdep
+
+
+machdep = make_machdep()
+
+compilation_command = [args.compiler]
+
+for flag in args.cpp_arch_flags + args.compiler_flags:
+    compilation_command = compilation_command + flag.split(" ")
+
+source_files = [
+    # sanity_check is juste here to ensure that the given compiler
+    # and flags are coherent. It must be kept at the top of the list.
+    ("sanity_check.c", "none"),
+    ("sizeof_short.c", "number"),
+    ("sizeof_int.c", "number"),
+    ("sizeof_long.c", "number"),
+    ("sizeof_longlong.c", "number"),
+    ("sizeof_ptr.c", "number"),
+    ("sizeof_float.c", "number"),
+    ("sizeof_double.c", "number"),
+    ("sizeof_longdouble.c", "number"),
+    ("sizeof_void.c", "number"),
+    ("sizeof_fun.c", "number"),
+    ("alignof_short.c", "number"),
+    ("alignof_int.c", "number"),
+    ("alignof_long.c", "number"),
+    ("alignof_longlong.c", "number"),
+    ("alignof_ptr.c", "number"),
+    ("alignof_float.c", "number"),
+    ("alignof_double.c", "number"),
+    ("alignof_longdouble.c", "number"),
+    ("alignof_fun.c", "number"),
+    ("alignof_str.c", "number"),
+    ("alignof_aligned.c", "number"),
+    ("size_t.c", "type"),
+    ("ssize_t.c", "type"),
+    ("wchar_t.c", "type"),
+    ("ptrdiff_t.c", "type"),
+    ("intptr_t.c", "type"),
+    ("uintptr_t.c", "type"),
+    ("int_fast8_t.c", "type"),
+    ("int_fast16_t.c", "type"),
+    ("int_fast32_t.c", "type"),
+    ("int_fast64_t.c", "type"),
+    ("uint_fast8_t.c", "type"),
+    ("uint_fast16_t.c", "type"),
+    ("uint_fast32_t.c", "type"),
+    ("uint_fast64_t.c", "type"),
+    ("wint_t.c", "type"),
+    ("sig_atomic_t.c", "type"),
+    ("time_t.c", "type"),
+    ("char_is_unsigned.c", "bool"),
+    ("little_endian.c", "bool"),
+    ("has__builtin_va_list.c", "has__builtin_va_list"),
+    ("weof.c", "macro"),
+    ("wordsize.c", "macro"),
+    ("posix_version.c", "macro"),
+    ("limits_macros.c", "macro"),
+    ("stdio_macros.c", "macro"),
+    ("stdlib_macros.c", "macro"),
+    ("nsig.c", "macro"),
+    ("errno.c", "macrolist"),
+]
+
+
+def find_value(name, typ, output):
+    if typ == "bool":
+        expected = "(True|False)"
+
+        def conversion(x):
+            return x == "True"
+
+        default = False
+
+    elif typ == "number":
+        expected = "([0-9]+)"
+
+        def conversion(x):
+            return int(x)
+
+        default = -1
+
+    elif typ == "type":
+        expected = "`([^`]+)`"
+
+        def conversion(x):
+            return x
+
+        default = ""
+
+    else:
+        logging.warning(f"unexpected type '{typ}' for field '{name}', skipping")
+        return
+    if name in machdep:
+        msg = re.compile(name + " is " + expected)
+        res = re.search(msg, output)
+        if res:
+            value = conversion(res.group(1))
+            if args.verbose:
+                print(f"[INFO] setting {name} to {value}")
+            machdep[name] = value
+        else:
+            logging.warning(
+                f"cannot find value of field '{name}', using default value: '{default}'"
+            )
+            machdep[name] = default
+            if args.verbose:
+                print(f"compiler output is:{output}")
+    else:
+        logging.warning(f"unexpected symbol '{name}', ignoring")
+
+
+def cleanup_cpp(output):
+    lines = output.splitlines()
+    macro = filter(lambda s: s != "" and s[0] != "#", lines)
+    macro = map(lambda s: s.strip(), macro)
+    return " ".join(macro)
+
+
+def find_macros_value(output, is_list=False, entry=None):
+    msg = re.compile(r"(\w+)_is = ([^;]+);")
+    if is_list:
+        assert entry
+        machdep[entry] = {}
+    for res in re.finditer(msg, output):
+        name = res.group(1)
+        value = res.group(2).strip()
+        if is_list:
+            machdep[entry][name] = value
+        else:
+            if name in machdep:
+                if args.verbose:
+                    print(f"[INFO] setting {name} to {value}")
+                machdep[name] = value
+            else:
+                logging.warning(f"unexpected symbol '{name}', ignoring")
+    if args.verbose:
+        print(f"compiler output is:{output}")
+
+
+for f, typ in source_files:
+    p = my_path / f
+    cmd = compilation_command + [str(p)]
+    if typ in ("macro", "macrolist"):
+        # We're just interested in expanding a macro,
+        # treatment is a bit different than the rest.
+        cmd = cmd + ["-E"]
+    if args.verbose:
+        print(f"[INFO] running command: {' '.join(cmd)}")
+    proc = subprocess.run(cmd, capture_output=True)
+    Path(f).with_suffix(".o").unlink(missing_ok=True)
+    if typ == "none":
+        if proc.returncode != 0:
+            logging.critical("cannot compile sample C file with provided compiler and flags.")
+            logging.info(f"compiler output is:{proc.stderr.decode()}")
+            sys.exit(1)
+        continue
+    if typ == "macro":
+        if proc.returncode != 0:
+            logging.warning(f"error in preprocessing value '{p}', some values won't be filled")
+            if args.verbose:
+                print(f"compiler output is:{proc.stderr.decode()}")
+            name = p.stem
+            if name in machdep:
+                machdep[name] = ""
+            continue
+        find_macros_value(cleanup_cpp(proc.stdout.decode()))
+        continue
+    if typ == "macrolist":
+        name = p.stem
+        if proc.returncode != 0:
+            logging.warning(f"error in preprocessing value '{p}', some value might not be filled")
+            if args.verbose:
+                print(f"compiler output is:{proc.stderr.decode()}")
+            if name in machdep:
+                machdep[name] = {}
+            continue
+        find_macros_value(cleanup_cpp(proc.stdout.decode()), is_list=True, entry=name)
+        continue
+    if typ == "has__builtin_va_list":
+        # Special case: compilation success determines presence or absence
+        machdep["has__builtin_va_list"] = proc.returncode == 0
+        continue
+    if proc.returncode == 0:
+        # all tests should fail on an appropriate _Static_assert
+        # if compilation succeeds, we have a problem
+        logging.warning(f"WARNING: could not identify value of '{p.stem}', skipping")
+        continue
+    find_value(p.stem, typ, proc.stderr.decode())
+
+version_output = subprocess.run(
+    [args.compiler, args.compiler_version], capture_output=True, text=True
+)
+version = version_output.stdout.splitlines()[0]
+
+machdep["compiler"] = args.compiler
+machdep["cpp_arch_flags"] = args.cpp_arch_flags
+machdep["version"] = version
+
+machdep["custom_defs"] = ""
+
+# Extract predefined macros; we're assuming a gcc-like compiler here.
+# Leave custom_defs empty if this fails.
+
+# in case we have all the predefined macros, custom_defs will be very long.
+# we thus want to output it as a literal block, not a simple string.
+# For that, use a custom object and tell PyYaml to output it in a particular way
+# Based on SO's answer:
+
+
+class custom_defs(str):
+    pass
+
+
+def change_style(style, representer):
+    def new_representer(dumper, data):
+        scalar = representer(dumper, data)
+        scalar.style = style
+        return scalar
+
+    return new_representer
+
+
+custom_defs_representer = change_style("|", Representer.represent_str)
+
+yaml.add_representer(custom_defs, custom_defs_representer)
+
+cmd = compilation_command + ["-dM", "-E", "-"]
+if args.verbose:
+    print(f"[INFO] running command: {' '.join(cmd)}")
+proc = subprocess.run(cmd, stdin=subprocess.DEVNULL, capture_output=True, text=True)
+if proc.returncode == 0:
+    lines = ""
+    for line in proc.stdout.splitlines():
+        # Preprocessor emits a warning if we're trying to #undef
+        # standard macros. Leave them alone.
+        if re.match(r"#define *__STDC", line):
+            continue
+        macro = re.match(r"#define *(\w+)", line)
+        if macro:
+            lines += f"#undef {macro.group(1)}\n"
+        lines += f"{line.strip()}\n"
+    machdep["custom_defs"] = custom_defs(lines)
+else:
+    logging.warning("could not determine predefined macros")
+    if args.verbose:
+        print(f"compiler output is:{proc.stderr}")
+
+if args.from_file and args.in_place:
+    machdep["machdep_name"] = Path(args.from_file).stem
+elif args.dest_file:
+    machdep["machdep_name"] = Path(args.dest_file.name).stem
+else:
+    machdep["machdep_name"] = "anonymous_machdep"
+
+missing_fields = [f for [f, v] in machdep.items() if v is None]
+
+if missing_fields:
+    msg = ", ".join(missing_fields)
+    logging.warning(f"the following fields are missing from the machdep definition: {msg}")
+    for field in missing_fields:
+        machdep[field] = default_value(schema[field]["type"])
+
+print_machdep(machdep)
diff --git a/share/machdeps/make_machdep/make_machdep_common.h b/share/machdeps/make_machdep/make_machdep_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..8688084e084e41f03b2f8b0ec6af9a36d784fd8e
--- /dev/null
+++ b/share/machdeps/make_machdep/make_machdep_common.h
@@ -0,0 +1,44 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#if __STDC_VERSION__ < 201112L && !defined(__COMPCERT__)
+/* Try using a compiler builtin */
+#define ALIGNOF alignof
+#else
+#define ALIGNOF _Alignof
+#endif
+
+#if __STDC_VERSION__ >= 201112L || defined(__COMPCERT__)
+// Assume _Generic() is supported
+#define COMPATIBLE(T1, T2) _Generic(((T1){0}), T2 : 1, default : 0)
+#else
+// Expect that __builtin_types_compatible_p exists
+#define COMPATIBLE(T1, T2) (__builtin_types_compatible_p(T1, T2) ? 0x15 : 0xf4)
+#endif
+
+// needed to ensure the message is properly expanded for TEST_TYPE_IS
+#define mkstr(s) #s
+
+#define TEST_TYPE_COMPATIBLE(T1, T2)                                           \
+  _Static_assert(!COMPATIBLE(T1, T2), "" mkstr(T2) " is `" #T1 "`");
+
+#define TEST_TYPE_IS(type) TEST_TYPE_COMPATIBLE(type, TEST_TYPE)
diff --git a/share/machdeps/make_machdep/nsig.c b/share/machdeps/make_machdep/nsig.c
new file mode 100644
index 0000000000000000000000000000000000000000..e82b4fbe2eba34b9f74dfd6dcb0c7da9ccd53ea4
--- /dev/null
+++ b/share/machdeps/make_machdep/nsig.c
@@ -0,0 +1,29 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include <signal.h>
+
+#if defined(NSIG)
+int nsig_is = NSIG;
+#elif defined(_NSIG)
+int nsig_is = _NSIG;
+#endif
diff --git a/share/machdeps/make_machdep/posix_version.c b/share/machdeps/make_machdep/posix_version.c
new file mode 100644
index 0000000000000000000000000000000000000000..bdd131ffc0dace0035d2dcf3b2e6a71b2b1532fd
--- /dev/null
+++ b/share/machdeps/make_machdep/posix_version.c
@@ -0,0 +1,27 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include <unistd.h>
+
+#if defined(_POSIX_VERSION)
+long posix_version_is = _POSIX_VERSION;
+#endif
diff --git a/share/machdeps/make_machdep/ptrdiff_t.c b/share/machdeps/make_machdep/ptrdiff_t.c
new file mode 100644
index 0000000000000000000000000000000000000000..29c9d38d42b5ca332b0111761b323ff69d60b1fc
--- /dev/null
+++ b/share/machdeps/make_machdep/ptrdiff_t.c
@@ -0,0 +1,29 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+#include <stddef.h>
+#define TEST_TYPE ptrdiff_t
+
+TEST_TYPE_IS(int);
+TEST_TYPE_IS(long);
+TEST_TYPE_IS(long long);
diff --git a/share/machdeps/make_machdep/sanity_check.c b/share/machdeps/make_machdep/sanity_check.c
new file mode 100644
index 0000000000000000000000000000000000000000..8e38b55803d1543ab01368a639b9915aea4305e8
--- /dev/null
+++ b/share/machdeps/make_machdep/sanity_check.c
@@ -0,0 +1,24 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+/* ensure that the given compiler and flags support a minimal C file */
+int main () { }
diff --git a/share/machdeps/make_machdep/sig_atomic_t.c b/share/machdeps/make_machdep/sig_atomic_t.c
new file mode 100644
index 0000000000000000000000000000000000000000..9141b3d9a7c0261d419d9260bfb449c9a2b7bb78
--- /dev/null
+++ b/share/machdeps/make_machdep/sig_atomic_t.c
@@ -0,0 +1,38 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+#include <signal.h>
+
+#define TEST_TYPE sig_atomic_t
+
+TEST_TYPE_IS(char)
+TEST_TYPE_IS(unsigned char)
+TEST_TYPE_IS(signed char)
+TEST_TYPE_IS(unsigned short)
+TEST_TYPE_IS(short)
+TEST_TYPE_IS(unsigned int)
+TEST_TYPE_IS(int)
+TEST_TYPE_IS(unsigned long)
+TEST_TYPE_IS(long)
+TEST_TYPE_IS(unsigned long long)
+TEST_TYPE_IS(long long)
diff --git a/share/machdeps/make_machdep/size_t.c b/share/machdeps/make_machdep/size_t.c
new file mode 100644
index 0000000000000000000000000000000000000000..13a4685263cda07d1c57d97088bf9ee85f9b59a1
--- /dev/null
+++ b/share/machdeps/make_machdep/size_t.c
@@ -0,0 +1,30 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+#include <stddef.h>
+
+#define TEST_TYPE size_t
+
+TEST_TYPE_IS(unsigned int)
+TEST_TYPE_IS(unsigned long)
+TEST_TYPE_IS(unsigned long long)
diff --git a/share/machdeps/make_machdep/sizeof_double.c b/share/machdeps/make_machdep/sizeof_double.c
new file mode 100644
index 0000000000000000000000000000000000000000..c87c337250d403c4bce05eac6cf3f5197098132b
--- /dev/null
+++ b/share/machdeps/make_machdep/sizeof_double.c
@@ -0,0 +1,30 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+_Static_assert(sizeof(double) != 1, "sizeof_double is 1");
+_Static_assert(sizeof(double) != 2, "sizeof_double is 2");
+_Static_assert(sizeof(double) != 3, "sizeof_double is 3");
+_Static_assert(sizeof(double) != 4, "sizeof_double is 4");
+_Static_assert(sizeof(double) != 5, "sizeof_double is 5");
+_Static_assert(sizeof(double) != 6, "sizeof_double is 6");
+_Static_assert(sizeof(double) != 7, "sizeof_double is 7");
+_Static_assert(sizeof(double) != 8, "sizeof_double is 8");
diff --git a/share/machdeps/make_machdep/sizeof_float.c b/share/machdeps/make_machdep/sizeof_float.c
new file mode 100644
index 0000000000000000000000000000000000000000..6de246c1bde90eb86caec97394c703a2b6974c32
--- /dev/null
+++ b/share/machdeps/make_machdep/sizeof_float.c
@@ -0,0 +1,30 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+_Static_assert(sizeof(float) != 1, "sizeof_float is 1");
+_Static_assert(sizeof(float) != 2, "sizeof_float is 2");
+_Static_assert(sizeof(float) != 3, "sizeof_float is 3");
+_Static_assert(sizeof(float) != 4, "sizeof_float is 4");
+_Static_assert(sizeof(float) != 5, "sizeof_float is 5");
+_Static_assert(sizeof(float) != 6, "sizeof_float is 6");
+_Static_assert(sizeof(float) != 7, "sizeof_float is 7");
+_Static_assert(sizeof(float) != 8, "sizeof_float is 8");
diff --git a/share/machdeps/make_machdep/sizeof_fun.c b/share/machdeps/make_machdep/sizeof_fun.c
new file mode 100644
index 0000000000000000000000000000000000000000..daa499b72c920df365de255e1781bddbd0835802
--- /dev/null
+++ b/share/machdeps/make_machdep/sizeof_fun.c
@@ -0,0 +1,23 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+_Static_assert(sizeof(void()) != 1, "sizeof_fun is 1");
diff --git a/share/machdeps/make_machdep/sizeof_int.c b/share/machdeps/make_machdep/sizeof_int.c
new file mode 100644
index 0000000000000000000000000000000000000000..914fa6af09af11e6d7565b50c24b75ec6e7f5fe2
--- /dev/null
+++ b/share/machdeps/make_machdep/sizeof_int.c
@@ -0,0 +1,30 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+_Static_assert(sizeof(int) != 1, "sizeof_int is 1");
+_Static_assert(sizeof(int) != 2, "sizeof_int is 2");
+_Static_assert(sizeof(int) != 3, "sizeof_int is 3");
+_Static_assert(sizeof(int) != 4, "sizeof_int is 4");
+_Static_assert(sizeof(int) != 5, "sizeof_int is 5");
+_Static_assert(sizeof(int) != 6, "sizeof_int is 6");
+_Static_assert(sizeof(int) != 7, "sizeof_int is 7");
+_Static_assert(sizeof(int) != 8, "sizeof_int is 8");
diff --git a/share/machdeps/make_machdep/sizeof_long.c b/share/machdeps/make_machdep/sizeof_long.c
new file mode 100644
index 0000000000000000000000000000000000000000..a545896ddfcb6d6b26dccddd33268cfebeb87fda
--- /dev/null
+++ b/share/machdeps/make_machdep/sizeof_long.c
@@ -0,0 +1,30 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+_Static_assert(sizeof(long) != 1, "sizeof_long is 1");
+_Static_assert(sizeof(long) != 2, "sizeof_long is 2");
+_Static_assert(sizeof(long) != 3, "sizeof_long is 3");
+_Static_assert(sizeof(long) != 4, "sizeof_long is 4");
+_Static_assert(sizeof(long) != 5, "sizeof_long is 5");
+_Static_assert(sizeof(long) != 6, "sizeof_long is 6");
+_Static_assert(sizeof(long) != 7, "sizeof_long is 7");
+_Static_assert(sizeof(long) != 8, "sizeof_long is 8");
diff --git a/share/machdeps/make_machdep/sizeof_longdouble.c b/share/machdeps/make_machdep/sizeof_longdouble.c
new file mode 100644
index 0000000000000000000000000000000000000000..78922473994cf9d2305f426ab067079b4ba5fe04
--- /dev/null
+++ b/share/machdeps/make_machdep/sizeof_longdouble.c
@@ -0,0 +1,38 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+_Static_assert(sizeof(long double) != 1, "sizeof_longdouble is 1");
+_Static_assert(sizeof(long double) != 2, "sizeof_longdouble is 2");
+_Static_assert(sizeof(long double) != 3, "sizeof_longdouble is 3");
+_Static_assert(sizeof(long double) != 4, "sizeof_longdouble is 4");
+_Static_assert(sizeof(long double) != 5, "sizeof_longdouble is 5");
+_Static_assert(sizeof(long double) != 6, "sizeof_longdouble is 6");
+_Static_assert(sizeof(long double) != 7, "sizeof_longdouble is 7");
+_Static_assert(sizeof(long double) != 8, "sizeof_longdouble is 8");
+_Static_assert(sizeof(long double) != 9, "sizeof_longdouble is 9");
+_Static_assert(sizeof(long double) != 10, "sizeof_longdouble is 10");
+_Static_assert(sizeof(long double) != 11, "sizeof_longdouble is 11");
+_Static_assert(sizeof(long double) != 12, "sizeof_longdouble is 12");
+_Static_assert(sizeof(long double) != 13, "sizeof_longdouble is 13");
+_Static_assert(sizeof(long double) != 14, "sizeof_longdouble is 14");
+_Static_assert(sizeof(long double) != 15, "sizeof_longdouble is 15");
+_Static_assert(sizeof(long double) != 16, "sizeof_longdouble is 16");
diff --git a/share/machdeps/make_machdep/sizeof_longlong.c b/share/machdeps/make_machdep/sizeof_longlong.c
new file mode 100644
index 0000000000000000000000000000000000000000..246b21d6fdafe51191d9905439cf5db08b29a5d2
--- /dev/null
+++ b/share/machdeps/make_machdep/sizeof_longlong.c
@@ -0,0 +1,30 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+_Static_assert(sizeof(long long) != 1, "sizeof_longlong is 1");
+_Static_assert(sizeof(long long) != 2, "sizeof_longlong is 2");
+_Static_assert(sizeof(long long) != 3, "sizeof_longlong is 3");
+_Static_assert(sizeof(long long) != 4, "sizeof_longlong is 4");
+_Static_assert(sizeof(long long) != 5, "sizeof_longlong is 5");
+_Static_assert(sizeof(long long) != 6, "sizeof_longlong is 6");
+_Static_assert(sizeof(long long) != 7, "sizeof_longlong is 7");
+_Static_assert(sizeof(long long) != 8, "sizeof_longlong is 8");
diff --git a/share/machdeps/make_machdep/sizeof_ptr.c b/share/machdeps/make_machdep/sizeof_ptr.c
new file mode 100644
index 0000000000000000000000000000000000000000..d99d94fbcdde01a34d5d5c5db6d855c079c465ba
--- /dev/null
+++ b/share/machdeps/make_machdep/sizeof_ptr.c
@@ -0,0 +1,30 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+_Static_assert(sizeof(void *) != 1, "sizeof_ptr is 1");
+_Static_assert(sizeof(void *) != 2, "sizeof_ptr is 2");
+_Static_assert(sizeof(void *) != 3, "sizeof_ptr is 3");
+_Static_assert(sizeof(void *) != 4, "sizeof_ptr is 4");
+_Static_assert(sizeof(void *) != 5, "sizeof_ptr is 5");
+_Static_assert(sizeof(void *) != 6, "sizeof_ptr is 6");
+_Static_assert(sizeof(void *) != 7, "sizeof_ptr is 7");
+_Static_assert(sizeof(void *) != 8, "sizeof_ptr is 8");
diff --git a/share/machdeps/make_machdep/sizeof_short.c b/share/machdeps/make_machdep/sizeof_short.c
new file mode 100644
index 0000000000000000000000000000000000000000..5287ec206760c0bb43d3e5fd6d06ec016dd819dc
--- /dev/null
+++ b/share/machdeps/make_machdep/sizeof_short.c
@@ -0,0 +1,30 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+_Static_assert(sizeof(short) != 1, "sizeof_short is 1");
+_Static_assert(sizeof(short) != 2, "sizeof_short is 2");
+_Static_assert(sizeof(short) != 3, "sizeof_short is 3");
+_Static_assert(sizeof(short) != 4, "sizeof_short is 4");
+_Static_assert(sizeof(short) != 5, "sizeof_short is 5");
+_Static_assert(sizeof(short) != 6, "sizeof_short is 6");
+_Static_assert(sizeof(short) != 7, "sizeof_short is 7");
+_Static_assert(sizeof(short) != 8, "sizeof_short is 8");
diff --git a/share/machdeps/make_machdep/sizeof_void.c b/share/machdeps/make_machdep/sizeof_void.c
new file mode 100644
index 0000000000000000000000000000000000000000..76db3124db00720802a827e9f7b0cf54d836d7bf
--- /dev/null
+++ b/share/machdeps/make_machdep/sizeof_void.c
@@ -0,0 +1,23 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+_Static_assert(sizeof(void) != 1, "sizeof_void is 1");
diff --git a/share/machdeps/make_machdep/ssize_t.c b/share/machdeps/make_machdep/ssize_t.c
new file mode 100644
index 0000000000000000000000000000000000000000..3f8de4170d217c8a600929955bd79e2dc712602b
--- /dev/null
+++ b/share/machdeps/make_machdep/ssize_t.c
@@ -0,0 +1,32 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+#include <sys/types.h>
+
+#define TEST_TYPE ssize_t
+
+TEST_TYPE_IS(char)
+TEST_TYPE_IS(short)
+TEST_TYPE_IS(int)
+TEST_TYPE_IS(long)
+TEST_TYPE_IS(long long)
diff --git a/share/machdeps/make_machdep/stdio_macros.c b/share/machdeps/make_machdep/stdio_macros.c
new file mode 100644
index 0000000000000000000000000000000000000000..e332c2b35407bc8c29e99d2572cfd39aec6f4679
--- /dev/null
+++ b/share/machdeps/make_machdep/stdio_macros.c
@@ -0,0 +1,42 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include <stdio.h>
+
+#if defined(BUFSIZ)
+int bufsiz_is = BUFSIZ;
+#endif
+#if defined(EOF)
+int eof_is = EOF;
+#endif
+#if defined(FOPEN_MAX)
+int fopen_max_is = FOPEN_MAX;
+#endif
+#if defined(FILENAME_MAX)
+int filename_max_is = FILENAME_MAX;
+#endif
+#if defined(L_tmpnam)
+int l_tmpnam_is = L_tmpnam;
+#endif
+#if defined(TMP_MAX)
+int tmp_max_is = TMP_MAX;
+#endif
diff --git a/share/machdeps/make_machdep/stdlib_macros.c b/share/machdeps/make_machdep/stdlib_macros.c
new file mode 100644
index 0000000000000000000000000000000000000000..88ffd4f8014ff3ab136143ad37e62ca6bb1451b9
--- /dev/null
+++ b/share/machdeps/make_machdep/stdlib_macros.c
@@ -0,0 +1,36 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include <limits.h>
+#include <stdlib.h>
+
+#if defined(RAND_MAX)
+int rand_max_is = RAND_MAX;
+#endif
+
+/* NB: MB_LEN_MAX is the maximal value of MB_CUR_MAX;
+   however, the current Frama-C libc is not equipped to
+   fully deal with a non-constant MB_CUR_MAX
+*/
+#if defined(MB_LEN_MAX)
+size_t mb_cur_max_is = ((size_t)MB_LEN_MAX);
+#endif
diff --git a/share/machdeps/make_machdep/time_t.c b/share/machdeps/make_machdep/time_t.c
new file mode 100644
index 0000000000000000000000000000000000000000..2e1b90a172b9856d5053f0cc525c5396d37879f5
--- /dev/null
+++ b/share/machdeps/make_machdep/time_t.c
@@ -0,0 +1,39 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+#include <time.h>
+
+#define TEST_TYPE time_t
+
+TEST_TYPE_IS(unsigned int)
+TEST_TYPE_IS(int)
+TEST_TYPE_IS(unsigned long)
+TEST_TYPE_IS(long)
+TEST_TYPE_IS(unsigned long long)
+TEST_TYPE_IS(long long)
+
+// Technically, C standard speaks of a 'real' type, not an 'integer' one
+
+TEST_TYPE_IS(float)
+TEST_TYPE_IS(double)
+TEST_TYPE_IS(long double)
diff --git a/share/machdeps/make_machdep/uint_fast16_t.c b/share/machdeps/make_machdep/uint_fast16_t.c
new file mode 100644
index 0000000000000000000000000000000000000000..8b6524211c85d80f4089d79492e89ec7feabc559
--- /dev/null
+++ b/share/machdeps/make_machdep/uint_fast16_t.c
@@ -0,0 +1,31 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+#include <stdint.h>
+#define TEST_TYPE uint_fast16_t
+
+TEST_TYPE_IS(unsigned char);
+TEST_TYPE_IS(unsigned short);
+TEST_TYPE_IS(unsigned int);
+TEST_TYPE_IS(unsigned long);
+TEST_TYPE_IS(unsigned long long);
diff --git a/share/machdeps/make_machdep/uint_fast32_t.c b/share/machdeps/make_machdep/uint_fast32_t.c
new file mode 100644
index 0000000000000000000000000000000000000000..ff8e7cbe8f5157e82edb98ae4e4d5e63fd034514
--- /dev/null
+++ b/share/machdeps/make_machdep/uint_fast32_t.c
@@ -0,0 +1,31 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+#include <stdint.h>
+#define TEST_TYPE uint_fast32_t
+
+TEST_TYPE_IS(unsigned char);
+TEST_TYPE_IS(unsigned short);
+TEST_TYPE_IS(unsigned int);
+TEST_TYPE_IS(unsigned long);
+TEST_TYPE_IS(unsigned long long);
diff --git a/share/machdeps/make_machdep/uint_fast64_t.c b/share/machdeps/make_machdep/uint_fast64_t.c
new file mode 100644
index 0000000000000000000000000000000000000000..5dbc103bd28c963d211b051cebf5bf80e3fb18ff
--- /dev/null
+++ b/share/machdeps/make_machdep/uint_fast64_t.c
@@ -0,0 +1,31 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+#include <stdint.h>
+#define TEST_TYPE uint_fast64_t
+
+TEST_TYPE_IS(unsigned char);
+TEST_TYPE_IS(unsigned short);
+TEST_TYPE_IS(unsigned int);
+TEST_TYPE_IS(unsigned long);
+TEST_TYPE_IS(unsigned long long);
diff --git a/share/machdeps/make_machdep/uint_fast8_t.c b/share/machdeps/make_machdep/uint_fast8_t.c
new file mode 100644
index 0000000000000000000000000000000000000000..d7710d97b006d2a3f28f8eaa16b33af1e0340017
--- /dev/null
+++ b/share/machdeps/make_machdep/uint_fast8_t.c
@@ -0,0 +1,31 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+#include <stdint.h>
+#define TEST_TYPE uint_fast8_t
+
+TEST_TYPE_IS(unsigned char);
+TEST_TYPE_IS(unsigned short);
+TEST_TYPE_IS(unsigned int);
+TEST_TYPE_IS(unsigned long);
+TEST_TYPE_IS(unsigned long long);
diff --git a/share/machdeps/make_machdep/uintptr_t.c b/share/machdeps/make_machdep/uintptr_t.c
new file mode 100644
index 0000000000000000000000000000000000000000..655dd30616e2fd871f4f156702d71a4ba7eba77c
--- /dev/null
+++ b/share/machdeps/make_machdep/uintptr_t.c
@@ -0,0 +1,29 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+#include <stdint.h>
+#define TEST_TYPE uintptr_t
+
+TEST_TYPE_IS(unsigned int);
+TEST_TYPE_IS(unsigned long);
+TEST_TYPE_IS(unsigned long long);
diff --git a/share/machdeps/make_machdep/wchar_t.c b/share/machdeps/make_machdep/wchar_t.c
new file mode 100644
index 0000000000000000000000000000000000000000..ce5b3ae2a74ab4fb8f83f6a227f5aaf174cb9b70
--- /dev/null
+++ b/share/machdeps/make_machdep/wchar_t.c
@@ -0,0 +1,32 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+#include <stddef.h>
+#define TEST_TYPE wchar_t
+
+TEST_TYPE_IS(unsigned short)
+TEST_TYPE_IS(short)
+TEST_TYPE_IS(unsigned int)
+TEST_TYPE_IS(int)
+TEST_TYPE_IS(unsigned long)
+TEST_TYPE_IS(long)
diff --git a/share/machdeps/make_machdep/weof.c b/share/machdeps/make_machdep/weof.c
new file mode 100644
index 0000000000000000000000000000000000000000..f648ef8391c5408c06d27841062afed44ff29a31
--- /dev/null
+++ b/share/machdeps/make_machdep/weof.c
@@ -0,0 +1,27 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include <wchar.h>
+
+#if defined(WEOF)
+const wint_t weof_is = WEOF;
+#endif
diff --git a/share/machdeps/make_machdep/wint_t.c b/share/machdeps/make_machdep/wint_t.c
new file mode 100644
index 0000000000000000000000000000000000000000..bf7486460e5174a58545479652f1f754f6c5a76e
--- /dev/null
+++ b/share/machdeps/make_machdep/wint_t.c
@@ -0,0 +1,34 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include "make_machdep_common.h"
+#include <wchar.h>
+#define TEST_TYPE wint_t
+
+TEST_TYPE_IS(unsigned short);
+TEST_TYPE_IS(short);
+TEST_TYPE_IS(unsigned int);
+TEST_TYPE_IS(int);
+TEST_TYPE_IS(unsigned long);
+TEST_TYPE_IS(long);
+TEST_TYPE_IS(unsigned long long);
+TEST_TYPE_IS(long long);
diff --git a/share/machdeps/make_machdep/wordsize.c b/share/machdeps/make_machdep/wordsize.c
new file mode 100644
index 0000000000000000000000000000000000000000..7279411f73930f030a8f29a523d31d47759ee88f
--- /dev/null
+++ b/share/machdeps/make_machdep/wordsize.c
@@ -0,0 +1,27 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2023                                               */
+/*    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).            */
+/*                                                                        */
+/**************************************************************************/
+
+#include <features.h>
+
+#if defined(__WORDSIZE)
+const int wordsize_is = __WORDSIZE;
+#endif
diff --git a/src/dune b/src/dune
index 5d6871a6b48e4e14d9357782b90718e664b77aeb..599d3f7423ac6a0e1daba6de1ea8c204345e76e3 100644
--- a/src/dune
+++ b/src/dune
@@ -32,11 +32,14 @@
           (echo "  - dynlink:" %{lib-available:dynlink} "\n")
           (echo "  - bytes:" %{lib-available:bytes} "\n")
           (echo "  - yojson:" %{lib-available:yojson} "\n")
+          (echo "  - yaml.unix:" %{lib-available:yaml.unix} "\n")
+          (echo "  - fpath:" %{lib-available:fpath} "\n")
           (echo "  - menhirLib:" %{lib-available:menhirLib} "\n")
           (echo "  - dune-site:" %{lib-available:dune-site} "\n")
           (echo "  - dune-site.plugins:" %{lib-available:dune-site.plugins} "\n")
           (echo "  - ppx_import:" %{lib-available:ppx_import} "\n")
           (echo "  - ppx_deriving.eq:" %{lib-available:ppx_deriving.eq} "\n")
+          (echo "  - ppx_deriving_yaml:" %{lib-available:ppx_deriving_yaml} "\n")
   )
   )
 )
@@ -46,9 +49,9 @@
   (public_name frama-c.kernel)
   (foreign_stubs (language c) (names c_bindings))
   (flags :standard -w -9)
-  (libraries frama-c.init str unix zarith ocamlgraph dynlink bytes yojson menhirLib dune-site dune-site.plugins)
+  (libraries frama-c.init fpath str unix zarith ocamlgraph dynlink bytes yaml.unix yojson menhirLib dune-site dune-site.plugins)
   (instrumentation (backend landmarks))
-  (preprocess (staged_pps ppx_import ppx_deriving.eq))
+  (preprocess (staged_pps ppx_import ppx_deriving.eq ppx_deriving_yaml))
 )
 
 (generate_sites_module (module config_data) (sites frama-c) (plugins (frama-c plugins) (frama-c plugins_gui)))
diff --git a/src/kernel_internals/parsing/logic_parser.mly b/src/kernel_internals/parsing/logic_parser.mly
index d10a972435e8ed7c85c1a17a24a7063cabb66a11..45bdd477a8fa0e572ff6655507440f012cc5fca0 100644
--- a/src/kernel_internals/parsing/logic_parser.mly
+++ b/src/kernel_internals/parsing/logic_parser.mly
@@ -294,7 +294,6 @@
 %token PI
 
 %right prec_named
-%nonassoc TYPENAME
 %nonassoc prec_forall prec_exists prec_lambda LET
 %right QUESTION prec_question
 %left IFF
@@ -309,7 +308,6 @@
 %left STARHAT
 %left AMP
 %nonassoc IN
-%left LT
 %left LTLT GTGT
 %left PLUS MINUS
 %left STAR SLASH PERCENT
@@ -761,8 +759,8 @@ logic_rt_type:
 ;
 
 abs_spec_option:
-| /* empty */ %prec TYPENAME  { fun t -> t }
-| abs_spec { $1 }
+| /* empty */ { fun t -> t }
+| abs_spec    { $1 }
 ;
 
 abs_spec_cv_option:
@@ -772,12 +770,12 @@ abs_spec_cv_option:
 
 abs_spec:
 |                    tabs { $1 }
-| stars                   %prec TYPENAME { $1 }
-| stars              tabs                { fun t -> $2 ($1 t) }
-| stars abs_spec_bis      %prec TYPENAME { fun t -> $2 ($1 t) }
-| stars abs_spec_bis tabs                { fun t -> $2 ($3 ($1 t)) }
-|       abs_spec_bis tabs                { fun t -> $1 ($2 t) }
-|       abs_spec_bis      %prec TYPENAME { $1 }
+| stars                   { $1 }
+| stars              tabs { fun t -> $2 ($1 t) }
+| stars abs_spec_bis      { fun t -> $2 ($1 t) }
+| stars abs_spec_bis tabs { fun t -> $2 ($3 ($1 t)) }
+|       abs_spec_bis tabs { fun t -> $1 ($2 t) }
+|       abs_spec_bis      { $1 }
 ;
 
 abs_spec_cv:
@@ -813,7 +811,7 @@ stars_cv:
 ;
 
 tabs:
-| LSQUARE array_size RSQUARE %prec TYPENAME
+| LSQUARE array_size RSQUARE
     {
       fun t -> LTarray (t,$2)
     }
@@ -1659,10 +1657,11 @@ logic_def:
       exit_type_variables_scope ();
       LDpredicate_def (id, labels, tvars, $3, $5) }
 /* inductive predicate definition */
-| INDUCTIVE poly_id parameters LBRACE indcases RBRACE
-    { let (id,labels,tvars) = $2 in
-      exit_type_variables_scope ();
-      LDinductive_def(id, labels, tvars, $3, $5) }
+| INDUCTIVE pred = poly_id params = parameters
+    midrule({exit_type_variables_scope()})
+    LBRACE cases = indcases RBRACE
+    { let (id,labels,tvars) = pred in
+      LDinductive_def(id, labels, tvars, params, cases) }
 | LEMMA poly_id COLON lexpr SEMICOLON
     { let (id,labels,tvars) = $2 in
       exit_type_variables_scope ();
diff --git a/src/kernel_internals/runtime/machdep.ml b/src/kernel_internals/runtime/machdep.ml
new file mode 100644
index 0000000000000000000000000000000000000000..9ca2d913b5b020f1358e914adf3c6bd1990eae39
--- /dev/null
+++ b/src/kernel_internals/runtime/machdep.ml
@@ -0,0 +1,313 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2023                                               *)
+(*    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
+
+let gen_define fmt macro pp def =
+  Format.fprintf fmt "#define %s %a@\n" macro pp def
+
+let gen_include fmt file =
+  Format.fprintf fmt "#include <%s>@\n" file
+
+let gen_undef fmt macro = Format.fprintf fmt "#undef %s@\n" macro
+
+let gen_define_string fmt macro def =
+  gen_define fmt macro Format.pp_print_string def
+
+let gen_define_literal_string fmt macro def =
+  gen_define fmt macro Format.pp_print_string ("\"" ^ def ^ "\"")
+
+let gen_define_macro fmt macro def =
+  if def = "" then gen_undef fmt macro
+  else gen_define_string fmt macro def
+
+let gen_define_int fmt macro def = gen_define fmt macro Format.pp_print_int def
+
+let gen_byte_order fmt mach =
+  gen_define_string fmt "__FC_BYTE_ORDER"
+    (if mach.little_endian then "__LITTLE_ENDIAN" else "__BIG_ENDIAN")
+
+let no_signedness s =
+  let s = Option.value  ~default:s (Extlib.string_del_prefix "signed" s) in
+  let s = Option.value  ~default:s (Extlib.string_del_prefix "unsigned" s) in
+  let s = String.trim s in
+  if s = "" then "int" else s
+
+let suff_of_kind =
+  [ "char", "";
+    "short", "";
+    "int", "";
+    "long", "L";
+    "long long", "LL"
+  ]
+
+let pp_of_kind =
+  [ "char", "hh";
+    "short", "h";
+    "int", "";
+    "long", "l";
+    "long long", "ll"
+  ]
+
+let max_val bitsize is_signed kind =
+  let suff = List.assoc kind suff_of_kind in
+  let suff = if is_signed then suff else "U" ^ suff in
+  let to_shift = if is_signed then bitsize - 1 else bitsize in
+  let v = Z.(to_string (sub (shift_left one to_shift) one)) in
+  v ^ suff
+
+let min_val bitsize kind =
+  let suff = List.assoc kind suff_of_kind in
+  "(-" ^ (max_val bitsize true kind) ^ " - 1" ^ suff ^")"
+
+let gen_define_stype fmt name kind =
+  gen_define_string fmt ("__INT" ^ name ^ "_T") ("signed " ^ kind)
+let gen_define_utype fmt name kind =
+  gen_define_string fmt ("__UINT" ^ name ^ "_T") ("unsigned " ^ kind)
+let gen_define_min_stype fmt name bitsize kind =
+  gen_define_string fmt ("__INT" ^ name ^ "_MIN") (min_val bitsize kind)
+let gen_define_max_stype fmt name bitsize kind =
+  gen_define_string fmt ("__INT" ^ name ^ "_MAX") (max_val bitsize true kind)
+let gen_define_max_utype fmt name bitsize kind =
+  gen_define_string fmt ("__UINT" ^ name ^ "_MAX") (max_val bitsize false kind)
+
+let gen_std_signed fmt name bitsize kind =
+  gen_define_string fmt ("__FC_" ^ name ^ "_MIN") (min_val bitsize kind);
+  gen_define_string fmt ("__FC_" ^ name ^ "_MAX") (max_val bitsize true kind)
+
+let gen_std_unsigned fmt name bitsize kind =
+  gen_define_string fmt ("__FC_" ^ name ^ "_MAX") (max_val bitsize false kind)
+
+let gen_define_printing_prefix fmt name kind =
+  gen_define_literal_string fmt
+    ("__PRI" ^ name ^ "_PREFIX")
+    (List.assoc kind pp_of_kind)
+
+let gen_sizeof fmt name size =
+  gen_define_int fmt ("__SIZEOF_" ^ name) size
+
+let existing_int_size mach =
+  [ 1, "char";
+    mach.sizeof_short, "short";
+    mach.sizeof_int, "int";
+    mach.sizeof_long, "long";
+    mach.sizeof_longlong, "long long"]
+
+let std_type_name mach =
+  [ "char", if mach.char_is_unsigned then ("UCHAR", false) else ("SCHAR", true);
+    "signed char", ("SCHAR", true);
+    "unsigned char", ("UCHAR", false);
+    "short", ("SHRT", true);
+    "signed short", ("SHRT", true);
+    "unsigned short", ("USHRT", false);
+    "int", ("INT", true);
+    "signed", ("INT", true);
+    "signed int", ("INT", true);
+    "unsigned", ("UINT", false);
+    "unsigned int", ("UINT", false);
+    "long", ("LONG", true);
+    "signed long", ("LONG", true);
+    "unsigned long", ("ULONG", false);
+    "long long", ("LLONG", true);
+    "signed long long", ("LLONG" ,true);
+    "unsigned long long", ("ULLONG", false)
+  ]
+
+let gen_int_type_family fmt name bitsize kind =
+  gen_define_stype fmt name kind;
+  gen_define_utype fmt name kind;
+  gen_define_min_stype fmt name bitsize kind;
+  gen_define_max_stype fmt name bitsize kind;
+  gen_define_max_utype fmt name bitsize kind;
+  gen_define_printing_prefix fmt name kind
+
+let gen_fixed_size_family fmt bitsize mach =
+  let size = bitsize / 8 in
+  match
+    List.find_opt (fun (s,_) -> s >= size) (existing_int_size mach)
+  with
+  | None -> () (* No corresponding type. *)
+  | Some (exact_size, kind) ->
+    if size = exact_size then
+      gen_int_type_family fmt (string_of_int bitsize) bitsize kind;
+    gen_int_type_family fmt ("_LEAST" ^ string_of_int bitsize) bitsize kind
+
+let gen_max_size_int fmt mach =
+  gen_int_type_family fmt "MAX" (8 * mach.sizeof_longlong) "long long"
+
+let gen_std_min_max fmt mach =
+  gen_std_signed fmt "SCHAR" 8 "char";
+  gen_std_unsigned fmt "UCHAR" 8 "char";
+  gen_std_signed fmt "SHRT" (8*mach.sizeof_short) "short";
+  gen_std_unsigned fmt "USHRT" (8*mach.sizeof_short) "short";
+  gen_std_signed fmt "INT" (8*mach.sizeof_int) "int";
+  gen_std_unsigned fmt "UINT" (8*mach.sizeof_int) "int";
+  gen_std_signed fmt "LONG" (8*mach.sizeof_long) "long";
+  gen_std_unsigned fmt "ULONG" (8*mach.sizeof_long) "long";
+  gen_std_signed fmt "LLONG" (8*mach.sizeof_longlong) "long long";
+  gen_std_unsigned fmt "ULLONG" (8*mach.sizeof_longlong) "long long"
+
+let gen_va_list_repr fmt mach =
+  let repr =
+    if mach.has__builtin_va_list then "__builtin_va_list" else "char*"
+  in
+  gen_define_string fmt "__FC_VA_LIST_T" repr
+
+let gen_char_unsigned_flag fmt mach =
+  let macro = "__CHAR_UNSIGNED__" in
+  if mach.char_is_unsigned then gen_define_string fmt macro "1"
+  else gen_undef fmt macro
+
+let gen_sizeof_std fmt mach =
+  gen_sizeof fmt "SHORT" mach.sizeof_short;
+  gen_sizeof fmt "INT" mach.sizeof_int;
+  gen_sizeof fmt "LONG" mach.sizeof_long;
+  gen_sizeof fmt "LONGLONG" mach.sizeof_longlong
+
+let gen_intlike_min fmt name repr mach =
+  if repr <> "" then begin
+    let macro = name ^ "_MIN" in
+    let repr_name, is_signed = List.assoc repr (std_type_name mach) in
+    if is_signed then gen_define_string fmt macro ("__FC_" ^ repr_name ^ "_MIN")
+    else gen_define_int fmt macro 0
+  end
+
+let gen_intlike_max fmt name repr mach =
+  if repr <> "" then begin
+    let macro = name ^ "_MAX" in
+    let repr_name, _ = List.assoc repr (std_type_name mach) in
+    gen_define_string fmt macro ("__FC_" ^ repr_name ^ "_MAX")
+  end
+
+let gen_fast_int fmt bitsize signed repr mach =
+  let name = Format.sprintf "_FAST%d" bitsize in
+  let full_name =
+    Format.sprintf "__%sINT%s" (if signed then "" else "U") name
+  in
+  gen_define_string fmt (full_name ^ "_T") repr;
+  if signed then gen_intlike_min fmt full_name repr mach;
+  gen_intlike_max fmt full_name repr mach;
+  if signed then gen_define_printing_prefix fmt name (no_signedness repr)
+
+(* assuming all archs have an 8-bit char. In any case, if we end up dealing
+   with something else at some point, machdep will not be the only place were
+   changes will be required. *)
+let gen_char_bit fmt _mach =
+  gen_define_int fmt "__CHAR_BIT" 8
+
+let gen_define_errno_macro fmt (name, v) =
+  gen_define_string fmt ("__FC_" ^ (String.uppercase_ascii name)) v
+
+let machdep_macro_name s =
+  let tr = function
+    | c when 'a' <= c && c <= 'z' -> Char.uppercase_ascii c
+    | c when 'A' <= c && c <= 'Z' -> c
+    | c when '0' <= c && c <= '9' -> c
+    | _ -> '_'
+  in
+  String.map tr s
+
+let gen_all_defines fmt mach =
+  Format.fprintf fmt "/* Machdep-specific info for Frama-C's libc */@\n";
+  Format.fprintf fmt "#ifndef __FC_MACHDEP@\n#define __FC_MACHDEP@\n";
+  gen_define_int fmt ("__FC_" ^ (machdep_macro_name mach.machdep_name)) 1;
+  gen_byte_order fmt mach;
+  gen_fixed_size_family fmt 8 mach;
+  gen_fixed_size_family fmt 16 mach;
+  gen_fixed_size_family fmt 32 mach;
+  gen_fixed_size_family fmt 64 mach;
+  gen_fast_int fmt 8 true mach.int_fast8_t mach;
+  gen_fast_int fmt 16 true mach.int_fast16_t mach;
+  gen_fast_int fmt 32 true mach.int_fast32_t mach;
+  gen_fast_int fmt 64 true mach.int_fast64_t mach;
+  gen_fast_int fmt 8 false mach.uint_fast8_t mach;
+  gen_fast_int fmt 16 false mach.uint_fast16_t mach;
+  gen_fast_int fmt 32 false mach.uint_fast32_t mach;
+  gen_fast_int fmt 64 false mach.uint_fast64_t mach;
+  gen_max_size_int fmt mach;
+  gen_std_min_max fmt mach;
+  gen_va_list_repr fmt mach;
+  gen_char_unsigned_flag fmt mach;
+  gen_sizeof_std fmt mach;
+  gen_char_bit fmt mach;
+  gen_define_string fmt "__PTRDIFF_T" mach.ptrdiff_t;
+  gen_define_string fmt "__SIZE_T" mach.size_t;
+  gen_define_string fmt "__WCHAR_T" mach.wchar_t;
+  gen_define_string fmt "__INTPTR_T" mach.intptr_t;
+  gen_define_string fmt "__UINTPTR_T" mach.uintptr_t;
+  gen_define_string fmt "__PTRDIFF_T" mach.ptrdiff_t;
+  gen_define_string fmt "__WINT_T" mach.wint_t;
+  gen_define_string fmt "__SSIZE_T" mach.ssize_t;
+  gen_intlike_max fmt "__FC_SIZE" mach.size_t mach;
+  gen_intlike_min fmt "__FC_INTPTR" mach.intptr_t mach;
+  gen_intlike_max fmt "__FC_INTPTR" mach.intptr_t mach;
+  gen_intlike_max fmt "__FC_UINTPTR" mach.uintptr_t mach;
+  gen_intlike_min fmt "__FC_WCHAR" mach.wchar_t mach;
+  gen_intlike_max fmt "__FC_WCHAR" mach.wchar_t mach;
+  gen_intlike_max fmt "__SSIZE" mach.ssize_t mach;
+  gen_intlike_min fmt "__FC_PTRDIFF" mach.ptrdiff_t mach;
+  gen_intlike_max fmt "__FC_PTRDIFF" mach.ptrdiff_t mach;
+  gen_intlike_min fmt "__FC_WINT" mach.wint_t mach;
+  gen_intlike_max fmt "__FC_WINT" mach.wint_t mach;
+  gen_define_macro fmt "__FC_WEOF" mach.weof;
+  (* NB: Frama-C's inttypes.h is assuming that intptr_t and uintptr_t have the
+     same rank when it comes to define PRI.?PTR macros. *)
+  gen_define_literal_string fmt "__PRIPTR_PREFIX"
+    (List.assoc (no_signedness mach.intptr_t) pp_of_kind);
+  gen_define_macro fmt "__WORDSIZE" mach.wordsize;
+  gen_define_macro fmt "__FC_POSIX_VERSION" mach.posix_version;
+  gen_define_string fmt "__FC_SIG_ATOMIC_T" mach.sig_atomic_t;
+  gen_intlike_min fmt "__FC_SIG_ATOMIC_MIN" mach.sig_atomic_t mach;
+  gen_intlike_max fmt "__FC_SIG_ATOMIC_MAX" mach.sig_atomic_t mach;
+  gen_define_macro fmt "__FC_BUFSIZ" mach.bufsiz;
+  gen_define_macro fmt "__FC_EOF" mach.eof;
+  gen_define_macro fmt "__FC_FOPEN_MAX" mach.fopen_max;
+  gen_define_macro fmt "__FC_FILENAME_MAX" mach.filename_max;
+  gen_define_macro fmt "__FC_L_tmpnam" mach.l_tmpnam;
+  gen_define_macro fmt "__FC_TMP_MAX" mach.tmp_max;
+  gen_define_macro fmt "__FC_RAND_MAX" mach.rand_max;
+  gen_define_macro fmt "__FC_MB_CUR_MAX" mach.mb_cur_max;
+  gen_define_macro fmt "__FC_PATH_MAX" mach.path_max;
+  gen_define_macro fmt "__FC_HOST_NAME_MAX" mach.host_name_max;
+  gen_define_macro fmt "__FC_TTY_NAME_MAX" mach.tty_name_max;
+  List.iter (gen_define_errno_macro fmt) mach.errno;
+  gen_define_macro fmt "__FC_TIME_T" mach.time_t;
+  gen_define_macro fmt "__FC_NSIG" mach.nsig;
+  (* NB: should we use Cil.gccMode() here? *)
+  if mach.compiler = "gcc" then
+    gen_include fmt "__fc_gcc_builtins.h";
+
+  Format.fprintf fmt "%s@\n" mach.custom_defs;
+
+  Format.fprintf fmt "#endif // __FC_MACHDEP@\n"
+
+let generate_machdep_header mach =
+  let debug = Kernel.(is_debug_key_enabled dkey_pp) in
+  let temp = Extlib.temp_dir_cleanup_at_exit ~debug "__fc_machdep" in
+  let temp = Filepath.Normalized.of_string temp in
+  let file = Filepath.Normalized.concat temp "__fc_machdep.h" in
+  let chan = open_out (file:>string) in
+  let fmt = Format.formatter_of_out_channel chan in
+  gen_all_defines fmt mach;
+  flush chan;
+  close_out chan;
+  temp
diff --git a/src/plugins/gui/GSourceView.2.ml b/src/kernel_internals/runtime/machdep.mli
similarity index 76%
rename from src/plugins/gui/GSourceView.2.ml
rename to src/kernel_internals/runtime/machdep.mli
index 6e7db298617595bf60430041972be9314ed52fd3..8b4118076abaed9de7cb95cf8b3b47e7f67d6ec8 100644
--- a/src/plugins/gui/GSourceView.2.ml
+++ b/src/kernel_internals/runtime/machdep.mli
@@ -20,18 +20,14 @@
 (*                                                                        *)
 (**************************************************************************)
 
-(** compatibility layer between gtksourceview 2 and 3. *)
-include GSourceView2
+(** Managing machine-dependent information. *)
 
-let make_marker_attributes
-    ~(source:source_view)
-    ~(category:string)
-    ~(priority: int)
-    ?(background: Gdk.color option)
-    ?(pixbuf:GdkPixbuf.pixbuf option)
-    ?(icon_name:string option)
-    () =
-  ignore icon_name; (* not in lablgtk2. *)
-  source#set_mark_category_priority ~category priority;
-  source#set_mark_category_pixbuf ~category pixbuf;
-  source#set_mark_category_background ~category background
+
+(** Prints on the given formatter all [#define] directives
+    required by [share/libc/features.h] and other system-dependent headers.
+*)
+val gen_all_defines: Format.formatter -> Cil_types.mach -> unit
+
+(** generates a [__fc_machdep.h] file in a temp directory and returns the
+    directory name, to be added to the search path for preprocessing stdlib *)
+val generate_machdep_header: Cil_types.mach -> Filepath.Normalized.t
diff --git a/src/kernel_internals/runtime/machdeps.ml b/src/kernel_internals/runtime/machdeps.ml
deleted file mode 100644
index a1a9726e4b79fca10ffcb7eba109f71a04c27fd9..0000000000000000000000000000000000000000
--- a/src/kernel_internals/runtime/machdeps.ml
+++ /dev/null
@@ -1,239 +0,0 @@
-(****************************************************************************)
-(*                                                                          *)
-(*  Copyright (C) 2001-2003                                                 *)
-(*   George C. Necula    <necula@cs.berkeley.edu>                           *)
-(*   Scott McPeak        <smcpeak@cs.berkeley.edu>                          *)
-(*   Wes Weimer          <weimer@cs.berkeley.edu>                           *)
-(*   Ben Liblit          <liblit@cs.berkeley.edu>                           *)
-(*  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)                            *)
-(*               and INRIA (Institut National de Recherche en Informatique  *)
-(*                          et Automatique).                                *)
-(****************************************************************************)
-
-open Cil_types
-
-let x86_16 = {
-  version          =
-    "x86 16 bits mode (gcc like compiler) with big or huge memory model";
-  compiler = "generic";
-  cpp_arch_flags   = ["-m16"];
-  sizeof_short     = 2;
-  sizeof_int       = 2;
-  sizeof_long      = 4;
-  sizeof_longlong  = 8;
-  sizeof_ptr       = 4;
-  sizeof_float     = 4;
-  sizeof_double    = 8;
-  sizeof_longdouble  = 16;
-  sizeof_void      = -1;
-  sizeof_fun       = -1;
-  size_t = "unsigned int";
-  wchar_t = "int";
-  ptrdiff_t = "int";
-  alignof_short = 2;
-  alignof_int = 2;
-  alignof_long = 4;
-  alignof_longlong = 4;
-  alignof_ptr = 4;
-  alignof_float = 2;
-  alignof_double = 8;
-  alignof_longdouble = 16;
-  alignof_str = 1;
-  alignof_fun = -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;
-  underscore_name = true ;
-  has__builtin_va_list = true;
-}
-
-let gcc_x86_16 = { x86_16 with
-                   compiler = "gcc";
-                   sizeof_void = 1; sizeof_fun = 1; alignof_fun = 1;
-                 }
-
-let x86_32 = {
-  version          = "gcc 4.0.3 - X86-32bits mode";
-  compiler         = "generic";
-  cpp_arch_flags   = ["-m32"];
-  sizeof_short     = 2;
-  sizeof_int       = 4;
-  sizeof_long      = 4;
-  sizeof_longlong  = 8;
-  sizeof_ptr       = 4;
-  sizeof_float     = 4;
-  sizeof_double    = 8;
-  sizeof_longdouble  = 12;
-  sizeof_void      = -1;
-  sizeof_fun       = -1;
-  size_t = "unsigned int";
-  wchar_t = "int";
-  ptrdiff_t = "int";
-  alignof_short = 2;
-  alignof_int = 4;
-  alignof_long = 4;
-  alignof_longlong = 4;
-  alignof_ptr = 4;
-  alignof_float = 4;
-  alignof_double = 4;
-  alignof_longdouble = 4;
-  alignof_str = 1;
-  alignof_fun = -1;
-  alignof_aligned= 16;
-  char_is_unsigned = false;
-  const_string_literals = true;
-  little_endian = true;
-  underscore_name = false ;
-  has__builtin_va_list = true;
-}
-
-let gcc_x86_32 = { x86_32 with
-                   compiler = "gcc";
-                   sizeof_void = 1; sizeof_fun = 1; alignof_fun = 1;
-                 }
-
-let x86_64 = {
-  version          = "gcc 4.0.3 AMD64";
-  compiler         = "generic";
-  cpp_arch_flags   = ["-m64"];
-  sizeof_short     = 2;
-  sizeof_int       = 4;
-  sizeof_long      = 8;
-  sizeof_longlong  = 8;
-  sizeof_ptr       = 8;
-  sizeof_float     = 4;
-  sizeof_double    = 8;
-  sizeof_longdouble  = 16;
-  sizeof_void      = -1;
-  sizeof_fun       = -1;
-  size_t = "unsigned long";
-  wchar_t = "int";
-  ptrdiff_t = "long";
-  alignof_short = 2;
-  alignof_int = 4;
-  alignof_long = 8;
-  alignof_longlong = 8;
-  alignof_ptr = 8;
-  alignof_float = 4;
-  alignof_double = 8;
-  alignof_longdouble = 16;
-  alignof_str = 1;
-  alignof_fun = -1;
-  alignof_aligned= 16;
-  char_is_unsigned = false;
-  const_string_literals = true;
-  little_endian = true;
-  underscore_name = false ;
-  has__builtin_va_list = true;
-}
-
-let gcc_x86_64 = { x86_64 with
-                   compiler = "gcc";
-                   sizeof_void = 1; sizeof_fun = 1; alignof_fun = 1;
-                 }
-
-let ppc_32 = {
-  version          = "4.0.1 (Apple Computer, Inc. build 5367)";
-  compiler         = "standard";
-  cpp_arch_flags   = ["-m32"];
-  sizeof_short     = 2;
-  sizeof_int       = 4;
-  sizeof_long      = 4;
-  sizeof_longlong  = 8;
-  sizeof_ptr       = 4;
-  sizeof_float     = 4;
-  sizeof_double    = 8;
-  sizeof_longdouble  = 16;
-  sizeof_void      = 1;
-  sizeof_fun       = 1;
-  size_t = "unsigned int";
-  wchar_t = "int";
-  ptrdiff_t = "int";
-  alignof_short = 2;
-  alignof_int = 4;
-  alignof_long = 4;
-  alignof_longlong = 4;
-  alignof_ptr = 4;
-  alignof_float = 4;
-  alignof_double = 4;
-  alignof_longdouble = 16;
-  alignof_str = 1;
-  alignof_fun = 4;
-  alignof_aligned= 16;
-  char_is_unsigned = false;
-  const_string_literals = true;
-  little_endian = false;
-  underscore_name = false ;
-  has__builtin_va_list = true;
-}
-
-let msvc_x86_64 = {
-  version          = "MSVC - X86-64bits mode";
-  compiler         = "msvc";
-  cpp_arch_flags   = ["-m64"];
-  sizeof_short     = 2;
-  sizeof_int       = 4;
-  sizeof_long      = 4;
-  sizeof_longlong  = 8;
-  sizeof_ptr       = 8;
-  sizeof_float     = 4;
-  sizeof_double    = 8;
-  sizeof_longdouble  = 8;
-  sizeof_void      = 0;
-  sizeof_fun       = -1;
-  size_t = "unsigned long long"; (* defined as 'unsigned __int64' *)
-  wchar_t = "unsigned short";
-  ptrdiff_t = "long long"; (* defined as '__int64' *)
-  alignof_short = 2;
-  alignof_int = 4;
-  alignof_long = 4;
-  alignof_longlong = 8;
-  alignof_ptr = 8;
-  alignof_float = 4;
-  alignof_double = 8;
-  alignof_longdouble = 8;
-  alignof_str = 1; (* __alignof("a") results in compilation error C2059:
-                      syntax error: 'string' *)
-  alignof_fun = -1;
-  alignof_aligned= 1; (* MSVC does not seem to have an 'align' attribute
-                         equivalent to GCC's *)
-  char_is_unsigned = false;
-  const_string_literals = true;
-  little_endian = true;
-  underscore_name = false ;
-  has__builtin_va_list = false;
-}
diff --git a/src/kernel_internals/runtime/machdeps.mli b/src/kernel_internals/runtime/machdeps.mli
deleted file mode 100644
index 3959c84cf536c23ebd24c750f3695ef68911cefc..0000000000000000000000000000000000000000
--- a/src/kernel_internals/runtime/machdeps.mli
+++ /dev/null
@@ -1,54 +0,0 @@
-(****************************************************************************)
-(*                                                                          *)
-(*  Copyright (C) 2001-2003                                                 *)
-(*   George C. Necula    <necula@cs.berkeley.edu>                           *)
-(*   Scott McPeak        <smcpeak@cs.berkeley.edu>                          *)
-(*   Wes Weimer          <weimer@cs.berkeley.edu>                           *)
-(*   Ben Liblit          <liblit@cs.berkeley.edu>                           *)
-(*  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)                            *)
-(*               and INRIA (Institut National de Recherche en Informatique  *)
-(*                          et Automatique).                                *)
-(****************************************************************************)
-
-(** Some predefined {!Cil_types.mach} which specifies machine-dependent
-    data about C programs. *)
-
-val x86_16: Cil_types.mach
-val gcc_x86_16: Cil_types.mach
-val x86_32: Cil_types.mach
-val gcc_x86_32: Cil_types.mach
-val x86_64: Cil_types.mach
-val gcc_x86_64: Cil_types.mach
-val ppc_32: Cil_types.mach
-val msvc_x86_64: Cil_types.mach
diff --git a/src/kernel_internals/typing/cabs2cil.ml b/src/kernel_internals/typing/cabs2cil.ml
index a39379b17639f2b7b16fa30bc44001c212afbb3e..b6422e8030749d9da9814f232e4a68fa14bc868f 100644
--- a/src/kernel_internals/typing/cabs2cil.ml
+++ b/src/kernel_internals/typing/cabs2cil.ml
@@ -4494,9 +4494,9 @@ let checkTypedefSize name typ =
          (not exact && size < intended_size)
       then
         Kernel.warning ~current:true
-          "bad type '%a' (%d bits) for typedef '%s';@ \
+          "bad type '%a' (%d bits) for typedef '%s' using machdep %s;@ \
            check for mismatch between -machdep flag and headers used"
-          Typ.pretty typ size name
+          Typ.pretty typ size name Cil.theMachine.theMachine.machdep_name
     with
     (* Not a standard integer type, ignore it. *)
       Not_found -> ()
diff --git a/src/kernel_internals/typing/logic_builtin.ml b/src/kernel_internals/typing/logic_builtin.ml
index 629040d5995a1e5fb7d60d8ff15876f72c3aea2d..03c45e5023eafe2b3c686eb96f98e92a1898786f 100644
--- a/src/kernel_internals/typing/logic_builtin.ml
+++ b/src/kernel_internals/typing/logic_builtin.ml
@@ -118,6 +118,7 @@ let init =
           (fun c -> Logic_env.add_builtin_logic_ctor c.ctor_name c) ctors ;
         list.lt_def <- Some (LTsum ctors);
         let _list_of_integer = Ltype (list, [Linteger]) in
+        let l_label = FormalLabel "L" in
         (* predicates *)
         List.iter
           (fun (f,tparams,labels,params)  ->
@@ -154,14 +155,14 @@ let init =
             "\\no_overflow_double", [], [], ["m", rounding_mode; "x", Lreal] ;
             "\\subset", [a_name], [], ["s1", set_of_a_type;
                                        "s2", set_of_a_type];
-            "\\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)];
+            "\\pointer_comparable", [], [l_label], [("p1", object_ptr);
+                                                    ("p2", object_ptr)];
+            "\\pointer_comparable", [], [l_label], [("p1", fun_ptr);
+                                                    ("p2", fun_ptr)];
+            "\\pointer_comparable", [], [l_label], [("p1", fun_ptr);
+                                                    ("p2", object_ptr)];
+            "\\pointer_comparable", [], [l_label], [("p1", object_ptr);
+                                                    ("p2", fun_ptr)];
           ];
         (* functions *)
         List.iter
diff --git a/src/kernel_services/abstract_interp/cvalue.ml b/src/kernel_services/abstract_interp/cvalue.ml
index 4cbc4f03fee2715b7c53d9c7663b6b4d298e4085..31435f52e940154822a5ed8f287ba3b865d547b1 100644
--- a/src/kernel_services/abstract_interp/cvalue.ml
+++ b/src/kernel_services/abstract_interp/cvalue.ml
@@ -224,6 +224,20 @@ module V = struct
       (fun fmt (k, v) -> pp_base fmt k v)
       fmt m
 
+  let pretty_enumitem_set enuminfo fmt l =
+    let module S = Datatype.Integer.Map in
+    let assoc ei = Cil.constFoldToInt ei.eival |> Option.map (fun i -> i, ei) in
+    let lookup_map =
+      List.to_seq enuminfo.eitems |> Seq.filter_map assoc |> S.of_seq
+    in
+    let pretty_item fmt i =
+      match S.find_opt i lookup_map with
+      | Some ei -> Printer.pp_varname fmt ei.eiorig_name
+      | None -> Format.fprintf fmt "%a" Integer.pretty i
+    in
+    Pretty_utils.pp_iter ~pre:"@[<hov 1>{" ~suf:"}@]" ~sep:";@ "
+      List.iter pretty_item fmt l
+
   let pretty_typ typ fmt v =
     let pretty_org fmt org =
       if not (Origin.is_top org) then
@@ -239,7 +253,10 @@ module V = struct
         Base.SetLattice.pretty t pretty_org a
     | Map m ->
       try
-        Ival.pretty fmt (project_ival v)
+        let ival = project_ival v in
+        match Ival.project_small_set ival, Option.map Cil.unrollType typ with
+        | Some list, Some (TEnum (ei, _)) -> pretty_enumitem_set ei fmt list
+        | _ -> Ival.pretty fmt ival
       with
       | Not_based_on_null ->
         try
diff --git a/src/kernel_services/abstract_interp/function_Froms.ml b/src/kernel_services/abstract_interp/function_Froms.ml
index b5be5bfbcd8d6bdf37f36223138f6db489d69db9..f6f2f5e8a931121cbb58b2d66caf6c5fdaa4e3e5 100644
--- a/src/kernel_services/abstract_interp/function_Froms.ml
+++ b/src/kernel_services/abstract_interp/function_Froms.ml
@@ -105,7 +105,7 @@ struct
       indirect = Zone.join fd1.indirect fd2.indirect
     }
 
-  let _narrow fd1 fd2 = {
+  let narrow fd1 fd2 = {
     data = Zone.narrow fd1.data fd2.data;
     indirect = Zone.narrow fd1.indirect fd2.indirect
   }
diff --git a/src/kernel_services/abstract_interp/function_Froms.mli b/src/kernel_services/abstract_interp/function_Froms.mli
index d027b872e12325b7752219d768b1eb574d9e201e..141bfc5f9a5266c16d87476242410a5f7f679f83 100644
--- a/src/kernel_services/abstract_interp/function_Froms.mli
+++ b/src/kernel_services/abstract_interp/function_Froms.mli
@@ -31,7 +31,9 @@ module Deps : sig
 
   val bottom: deps
   val top: deps
+  val is_included: deps -> deps -> bool
   val join: deps -> deps -> deps
+  val narrow: deps -> deps -> deps
   val to_zone: deps -> Locations.Zone.t
 
   val add_data_dep: deps -> Locations.Zone.t -> deps
diff --git a/src/kernel_services/abstract_interp/int_set.ml b/src/kernel_services/abstract_interp/int_set.ml
index d4c45b4012f5f8d689e146ac34dcea3339bf10b4..47c3b99595189fb6c8d3d028ffa649fba37b71c6 100644
--- a/src/kernel_services/abstract_interp/int_set.ml
+++ b/src/kernel_services/abstract_interp/int_set.ml
@@ -111,12 +111,52 @@ let compare s1 s2 =
 
 let equal e1 e2 = compare e1 e2 = 0
 
+(* Used to print a compact representation of large integer sets. *)
+type set_or_itv =
+  | Set of Int.t array
+  | Itv of Int.t * Int.t
+
+(* Converts a set into an ordered list of sets and intervals, fusing adjacent
+   integers into intervals. *)
+let fuse_intervals s =
+  (* Add interval [b..e[ to the list [acc]. The interval can be a singleton. *)
+  let add_itv acc (b, e) =
+    let nb = Int.to_int_exn (Int.sub e b) in
+    (* If the interval is too small, uses a Set instead of Itv. *)
+    if nb > 3
+    then Itv (b, Int.pred e) :: acc
+    else
+      let a = Array.init nb (fun i -> Int.add b (Int.of_int i)) in
+      (* If the last element of [acc] is a Set, adds [a] at its end. *)
+      match acc with
+      | Set a' :: tl -> Set (Array.append a' a) :: tl
+      | _ -> Set a :: acc
+  in
+  (* [start..prev[ is the current interval being built. *)
+  let f (acc, start, prev) curr =
+    if Int.equal prev curr
+    then (acc, start, Int.succ curr)
+    else (add_itv acc (start, prev), curr, Int.succ curr)
+  in
+  let list, start, curr = Array.fold_left f ([], s.(0), s.(0)) s in
+  List.rev (add_itv list (start, curr))
+
+let pretty_array =
+  Pretty_utils.pp_iter ~pre:"@[<hov 1>{" ~suf:"}@]" ~sep:";@ "
+    Array.iter Int.pretty
+
+let pretty_set_or_itv fmt = function
+  | Set a -> pretty_array fmt a
+  | Itv (b, e) -> Format.fprintf fmt "[%a..%a]" Int.pretty b Int.pretty e
+
 let pretty fmt s =
-  Pretty_utils.pp_iter
-    ~pre:"@[<hov 1>{"
-    ~suf:"}@]"
-    ~sep:";@ "
-    Array.iter Int.pretty fmt s
+  if Array.length s < 10
+  then pretty_array fmt s
+  else
+    let union = Unicode.union_string () in
+    let sep = Scanf.format_from_string ("@ " ^ union ^ " ") "" in
+    Pretty_utils.pp_iter ~pre:"@[<hov 1>" ~suf:"@]" ~sep
+      List.iter pretty_set_or_itv fmt (fuse_intervals s)
 
 include Datatype.Make_with_collections
     (struct
diff --git a/src/kernel_services/abstract_interp/lattice_bounds.ml b/src/kernel_services/abstract_interp/lattice_bounds.ml
index 771b861ac05f3044f24b08d8f7d1ee7228478da8..1e48cad2696860e219610e9ed5df536a8fdd9c78 100644
--- a/src/kernel_services/abstract_interp/lattice_bounds.ml
+++ b/src/kernel_services/abstract_interp/lattice_bounds.ml
@@ -126,6 +126,10 @@ module Bottom = struct
 
   (* Iterators *)
 
+  let bind f = function
+    | `Bottom -> `Bottom
+    | `Value v -> f v
+
   let fold ~bottom f = function
     | `Bottom -> bottom
     | `Value v -> f v
@@ -170,17 +174,11 @@ module Bottom = struct
 
   module Operators =
   struct
-    let (>>-) t f = match t with
-      | `Bottom  -> `Bottom
-      | `Value t -> f t
-
-    let (>>-:) t f = match t with
-      | `Bottom  -> `Bottom
-      | `Value t -> `Value (f t)
-
-    let (let+) = (>>-:)
+    let (>>-) x f = bind f x
+    let (>>-:) x f = map f x
+    let (let+) x f = map f x
     let (and+) = zip
-    let (let*) = (>>-)
+    let (let*) x f = bind f x
     let (and*) = zip
   end
 
@@ -249,6 +247,20 @@ struct
     | `Top, v | v, `Top -> v
     | `Value vx, `Value vy -> `Value (narrow_value vx vy)
 
+  (* Iterators *)
+
+  let bind f = function
+    | `Top -> `Top
+    | `Value v -> f v
+
+  let fold ~top f = function
+    | `Top -> top
+    | `Value v -> f v
+
+  let map f = function
+    | `Top -> `Top
+    | `Value v -> `Value (f v)
+
   (** Combination *)
 
   let zip x y =
@@ -264,18 +276,13 @@ struct
 
   (** Operators *)
 
-  module Operators = struct
-    let (>>-) t f = match t with
-      | `Top -> `Top
-      | `Value t -> f t
-
-    let (>>-:) t f = match t with
-      | `Top -> `Top
-      | `Value t -> `Value (f t)
-
-    let (let+) = (>>-:)
+  module Operators =
+  struct
+    let (>>-) x f = bind f x
+    let (>>-:) x f = map f x
+    let (let+) x f = map f x
     let (and+) = zip
-    let (let*) = (>>-)
+    let (let*) x f = bind f x
     let (and*) = zip
   end
 end
@@ -299,6 +306,23 @@ struct
     | `Bottom, _ | _, `Bottom -> `Bottom
     | `Value vx, `Value vy -> (narrow_value vx vy :> 'a t)
 
+  (* Iterators *)
+
+  let bind f = function
+    | `Top -> `Top
+    | `Bottom -> `Bottom
+    | `Value v -> f v
+
+  let fold ~top ~bottom f = function
+    | `Top -> top
+    | `Bottom -> bottom
+    | `Value v -> f v
+
+  let map f = function
+    | `Top -> `Top
+    | `Bottom -> `Bottom
+    | `Value v -> `Value (f v)
+
   (** Combination *)
 
   let zip x y =
@@ -309,20 +333,13 @@ struct
 
   (** Operators *)
 
-  module Operators = struct
-    let (>>-) t f = match t with
-      | `Top -> `Top
-      | `Bottom -> `Bottom
-      | `Value t -> f t
-
-    let (>>-:) t f = match t with
-      | `Top -> `Top
-      | `Bottom -> `Bottom
-      | `Value t -> `Value (f t)
-
-    let (let+) = (>>-:)
+  module Operators =
+  struct
+    let (>>-) x f = bind f x
+    let (>>-:) x f = map f x
+    let (let+) x f = map f x
     let (and+) = zip
-    let (let*) = (>>-)
+    let (let*) x f = bind f x
     let (and*) = zip
   end
 end
diff --git a/src/kernel_services/abstract_interp/lattice_bounds.mli b/src/kernel_services/abstract_interp/lattice_bounds.mli
index 827f7856fffd3758e7f20cbe376c7aa1b1d918c5..ead45a00fb69b5e5aa017b8608dfa5039d605eb1 100644
--- a/src/kernel_services/abstract_interp/lattice_bounds.mli
+++ b/src/kernel_services/abstract_interp/lattice_bounds.mli
@@ -82,7 +82,8 @@ module Bottom : sig
 
   (* Iterators *)
   val iter: ('a -> unit) -> 'a t -> unit
-  val fold: bottom: 'b -> ('a -> 'b) -> 'a t -> 'b
+  val bind: ('a -> 'b t) -> 'a t -> 'b t
+  val fold: bottom:'b -> ('a -> 'b) -> 'a t -> 'b
   val map: ('a -> 'b) -> 'a t -> 'b t
 
   (* Combination *)
@@ -144,6 +145,12 @@ module Top : sig
   val join: ('a -> 'a -> 'a t) -> 'a t -> 'a t -> 'a t
   val narrow: ('a -> 'a -> 'a) -> 'a t -> 'a t -> 'a t
 
+  (* Iterators *)
+  val iter: ('a -> unit) -> 'a t -> unit
+  val bind: ('a -> 'b t) -> 'a t -> 'b t
+  val fold: top:'b -> ('a -> 'b) -> 'a t -> 'b
+  val map: ('a -> 'b) -> 'a t -> 'b t
+
   (** Combination *)
   val zip: 'a t -> 'b t -> ('a * 'b) t (* `Top if any is `Top *)
 
@@ -188,4 +195,10 @@ module TopBottom: sig
   (* Lattice operators *)
   val join: ('a -> 'a -> [< 'a t]) -> 'a t -> 'a t -> 'a t
   val narrow: ('a -> 'a -> [< 'a t]) -> 'a t -> 'a t -> 'a t
+
+  (* Iterators *)
+  val iter: ('a -> unit) -> 'a t -> unit
+  val bind: ('a -> 'b t) -> 'a t -> 'b t
+  val fold: top:'b -> bottom:'b -> ('a -> 'b) -> 'a t -> 'b
+  val map: ('a -> 'b) -> 'a t -> 'b t
 end
diff --git a/src/kernel_services/abstract_interp/lmap.ml b/src/kernel_services/abstract_interp/lmap.ml
index e4c673e3379f4eaab866138c315352445668bb48..4bc48a7c76ea0b922d8d9dc475ba0b474cafa94e 100644
--- a/src/kernel_services/abstract_interp/lmap.ml
+++ b/src/kernel_services/abstract_interp/lmap.ml
@@ -394,7 +394,7 @@ struct
       in
       let aux =
         generic_join ~cache:Hptmap_sig.NoCache
-          ~idempotent:true ~symmetric:true ~decide
+          ~idempotent:true ~symmetric:false ~decide
       in
       Format.fprintf fmt "@[<v>";
       ignore (aux m1 m2);
diff --git a/src/kernel_services/analysis/interpreted_automata.mli b/src/kernel_services/analysis/interpreted_automata.mli
index 5bf56988fb9028a19b02b66d559314891696bd12..b12dd9c6f0227bd108560e882ad3e8c05f7a195b 100644
--- a/src/kernel_services/analysis/interpreted_automata.mli
+++ b/src/kernel_services/analysis/interpreted_automata.mli
@@ -350,7 +350,7 @@ sig
     (** Same as [iter_stmt] but guarantee that the iteration will always
         be in the same increasing order of statements sid.
 
-        @since Frama-C+dev *)
+        @since 27.0-Cobalt *)
     val iter_stmt_asc : (Cil_types.stmt -> state -> unit) -> result -> unit
 
     (** Output result to the given channel. Must be supplied with a pretty
diff --git a/src/kernel_services/ast_data/annotations.ml b/src/kernel_services/ast_data/annotations.ml
index b30a7a868009fcd841748aec094e53cdf69104c1..4f049e0bf0d288ba0bb7bfbc4069a97ba6f97e0e 100644
--- a/src/kernel_services/ast_data/annotations.ml
+++ b/src/kernel_services/ast_data/annotations.ml
@@ -67,6 +67,9 @@ let find_englobing_kf ?kf stmt =
 (** {2 Internal State} *)
 (**************************************************************************)
 
+module Changed = Hook.Make()
+let add_hook_on_change = Changed.extend
+
 module Usable_emitter = struct
   include Emitter.Usable_emitter
   let local_clear _ h = Hashtbl.clear h
@@ -435,7 +438,8 @@ let pre_register_funspec ?tbl ?(emitter=Emitter.end_user) ?(force=false) kf =
           tbl;
     *)
     List.iter Property_status.register
-      (Property.ip_of_spec kf Kglobal ~active:[] spec)
+      (Property.ip_of_spec kf Kglobal ~active:[] spec);
+    Changed.apply();
   end
 
 let register_funspec ?emitter ?force kf =
@@ -767,7 +771,7 @@ let remove_code_annot_internal e ?(remove_statuses=true) ?kf stmt ca =
 (**************************************************************************)
 
 (* If this function gets exported, please turn e into an Emitter.t *)
-let remove_model_field (e:Usable_emitter.t) m =
+let do_remove_model_field (e:Usable_emitter.t) m =
   try
     let ty = m.mi_base_type in
     let h = Model_fields.find ty in
@@ -789,7 +793,7 @@ let remove_global e a =
          if Emitter.Usable_emitter.equal e e' then begin
            Globals.remove a;
            (match a with
-            | Dmodel_annot (m,_) -> remove_model_field e m
+            | Dmodel_annot (m,_) -> do_remove_model_field e m
             | _ -> ());
            let file = Ast.get () in
            file.globals <-
@@ -797,12 +801,14 @@ let remove_global e a =
                (fun a' ->
                   not (Global.equal (GAnnot(a, Global_annotation.loc a)) a'))
                file.globals;
-           Globals.apply_hooks_on_remove e a ()
+           Globals.apply_hooks_on_remove e a ();
+           Changed.apply();
          end)
       h;
   with Not_found ->
     ()
 
+(* internal use only *)
 let remove_in_funspec e kf set_spec =
   try
     let tbl = Funspecs.find kf in
@@ -815,7 +821,8 @@ let remove_in_funspec e kf set_spec =
           Format.printf "For emitter %a: %a@."
             Emitter.Usable_emitter.pretty e
             Cil_printer.pp_funspec spec) tbl; *)
-      set_spec spec tbl
+      set_spec spec tbl;
+      Changed.apply()
     with Not_found -> ()
   with Not_found ->
     assert false
@@ -845,7 +852,8 @@ let remove_behavior ?(force=false) e kf bhv =
   in
   remove_in_funspec e kf set_spec
 
-let remove_decreases e kf =
+(* internal use only *)
+let do_remove_decreases e kf =
   let set_spec spec _tbl =
     match spec.spec_variant with
     | None -> ()
@@ -855,7 +863,12 @@ let remove_decreases e kf =
   in
   remove_in_funspec e kf set_spec
 
-let remove_terminates e kf =
+let remove_decreases e kf =
+  do_remove_decreases e kf;
+  Changed.apply()
+
+(* internal use only *)
+let do_remove_terminates e kf =
   let set_spec spec _tbl =
     match spec.spec_terminates with
     | None -> ()
@@ -865,21 +878,36 @@ let remove_terminates e kf =
   in
   remove_in_funspec e kf set_spec
 
-let remove_complete e kf l =
+let remove_terminates e kf =
+  do_remove_terminates e kf;
+  Changed.apply()
+
+(* internal use only *)
+let do_remove_complete e kf l =
   let set_spec spec _tbl =
     spec.spec_complete_behaviors <- filterq l spec.spec_complete_behaviors
   in
   remove_in_funspec e kf set_spec;
   Property_status.remove (Property.ip_of_complete kf Kglobal ~active:[] l)
 
-let remove_disjoint e kf l =
+let remove_complete e kf l =
+  do_remove_complete e kf l;
+  Changed.apply()
+
+(* internal use only *)
+let do_remove_disjoint e kf l =
   let set_spec spec _tbl =
     spec.spec_disjoint_behaviors <- filterq l spec.spec_disjoint_behaviors
   in
   remove_in_funspec e kf set_spec;
   Property_status.remove (Property.ip_of_disjoint kf Kglobal ~active:[] l)
 
-let remove_requires e kf p =
+let remove_disjoint e kf l =
+  do_remove_disjoint e kf l;
+  Changed.apply()
+
+(* internal use only *)
+let do_remove_requires e kf p =
   let set_spec spec _tbl =
     List.iter
       (fun b ->
@@ -891,7 +919,12 @@ let remove_requires e kf p =
   in
   remove_in_funspec e kf set_spec
 
-let remove_assumes e kf p =
+let remove_requires e kf p =
+  do_remove_requires e kf p;
+  Changed.apply()
+
+(* internal use only *)
+let do_remove_assumes e kf p =
   let set_spec spec _tbl =
     List.iter
       (fun b ->
@@ -903,7 +936,12 @@ let remove_assumes e kf p =
   in
   remove_in_funspec e kf set_spec
 
-let remove_ensures e kf p =
+let remove_assumes e kf p =
+  do_remove_assumes e kf p;
+  Changed.apply()
+
+(* internal use only *)
+let do_remove_ensures e kf p =
   let set_spec spec _tbl =
     List.iter
       (fun b ->
@@ -915,7 +953,12 @@ let remove_ensures e kf p =
   in
   remove_in_funspec e kf set_spec
 
-let remove_allocates e kf p =
+let remove_ensures e kf p =
+  do_remove_ensures e kf p;
+  Changed.apply()
+
+(* internal use only *)
+let do_remove_allocates e kf p =
   let set_spec spec _tbl =
     List.iter
       (fun b ->
@@ -929,7 +972,12 @@ let remove_allocates e kf p =
   in
   remove_in_funspec e kf set_spec
 
-let remove_extended e kf ext =
+let remove_allocates e kf p =
+  do_remove_allocates e kf p;
+  Changed.apply()
+
+(* internal use only *)
+let do_remove_extended e kf ext =
   let set_spec spec _tbl =
     List.iter
       (fun b ->
@@ -940,8 +988,12 @@ let remove_extended e kf ext =
   in
   remove_in_funspec e kf set_spec
 
+let remove_extended e kf ext =
+  do_remove_extended e kf ext;
+  Changed.apply()
 
-let remove_assigns e kf p =
+(* internal use only *)
+let do_remove_assigns e kf p =
   let set_spec spec _tbl =
     List.iter
       (fun b ->
@@ -963,12 +1015,17 @@ let remove_assigns e kf p =
   in
   remove_in_funspec e kf set_spec
 
+let remove_assigns e kf p =
+  do_remove_assigns e kf p;
+  Changed.apply()
+
 let remove_behavior_components e kf b =
-  List.iter (remove_requires e kf) b.b_requires;
-  List.iter (remove_assumes e kf) b.b_assumes;
-  List.iter (remove_ensures e kf) b.b_post_cond;
-  remove_assigns e kf b.b_assigns;
-  remove_allocates e kf b.b_allocation
+  List.iter (do_remove_requires e kf) b.b_requires;
+  List.iter (do_remove_assumes e kf) b.b_assumes;
+  List.iter (do_remove_ensures e kf) b.b_post_cond;
+  do_remove_assigns e kf b.b_assigns;
+  do_remove_allocates e kf b.b_allocation;
+  Changed.apply()
 
 (**************************************************************************)
 (** {2 Adding annotations} *)
@@ -1080,7 +1137,8 @@ let mk_spec bhv variant terminates complete disjoint =
     spec_complete_behaviors = complete;
     spec_disjoint_behaviors = disjoint; }
 
-let add_behaviors ?(register_children=true) e kf ?stmt ?active bhvs =
+(* internal use only *)
+let do_add_behaviors ?(register_children=true) e kf ?stmt ?active bhvs =
   let full_spec = get_spec_all kf ?stmt ?active () in
   let emit_spec = get_spec_e e kf ?stmt ?active () in
   let existing_behaviors = emit_spec.spec_behavior in
@@ -1147,10 +1205,15 @@ let add_behaviors ?(register_children=true) e kf ?stmt ?active bhvs =
       bhvs
   end
 
+let add_behaviors ?register_children e kf ?stmt ?active bhvs =
+  do_add_behaviors ?register_children e kf ?stmt ?active bhvs;
+  Changed.apply()
+
 exception AlreadySpecified of string list
 
-let add_decreases ?(force=false) e kf v =
-  if force then remove_decreases e kf ;
+(* internal use only *)
+let do_add_decreases ?(force=false) e kf v =
+  if force then do_remove_decreases e kf ;
   let full_spec = get_spec_all kf () in
   let emit_spec = get_spec_e e kf () in
   (match full_spec.spec_variant with
@@ -1159,8 +1222,14 @@ let add_decreases ?(force=false) e kf v =
    | _ -> emit_spec.spec_variant <- Some v);
   Property_status.register (Property.ip_of_decreases kf Kglobal v)
 
-let add_terminates ?(force=false) e kf ?stmt ?active t =
-  if force then remove_terminates e kf ;
+(* internal use only *)
+let add_decreases ?force e kf v =
+  do_add_decreases ?force e kf v;
+  Changed.apply()
+
+(* internal use only *)
+let do_add_terminates ?(force=false) e kf ?stmt ?active t =
+  if force then do_remove_terminates e kf ;
   let full_spec = get_spec_all kf ?stmt ?active () in
   let emit_spec = get_spec_e e kf ?stmt ?active () in
   (match full_spec.spec_terminates with
@@ -1169,6 +1238,10 @@ let add_terminates ?(force=false) e kf ?stmt ?active t =
    | _ -> emit_spec.spec_terminates <- Some t);
   Property_status.register (Property.ip_of_terminates kf (kinstr stmt) t)
 
+let add_terminates ?force e kf ?stmt ?active t =
+  do_add_terminates ?force e kf ?stmt ?active t;
+  Changed.apply()
+
 let check_bhv_name spec name =
   if name = Cil.default_behavior_name then begin
     Kernel.fatal
@@ -1182,7 +1255,8 @@ let check_bhv_name spec name =
       name
   end
 
-let add_complete e kf ?stmt ?active l =
+(* internal use only *)
+let do_add_complete e kf ?stmt ?active l =
   let full_spec = get_spec_all kf ?stmt ?active () in
   let emit_spec = get_spec_e e kf ?stmt ?active () in
   if List.mem l full_spec.spec_complete_behaviors then
@@ -1198,7 +1272,12 @@ let add_complete e kf ?stmt ?active l =
       (Property.ip_of_complete kf (kinstr stmt) ~active l)
   end
 
-let add_disjoint e kf ?stmt ?active l =
+let add_complete e kf ?stmt ?active l =
+  do_add_complete e kf ?stmt ?active l;
+  Changed.apply()
+
+(* internal use only *)
+let do_add_disjoint e kf ?stmt ?active l =
   let full_spec = get_spec_all kf ?stmt ?active () in
   let emit_spec = get_spec_e e kf ?stmt ?active () in
   if List.mem l full_spec.spec_disjoint_behaviors then
@@ -1213,6 +1292,10 @@ let add_disjoint e kf ?stmt ?active l =
     Property_status.register (Property.ip_of_disjoint kf (kinstr stmt) ~active l)
   end
 
+let add_disjoint e kf ?stmt ?active l =
+  do_add_disjoint e kf ?stmt ?active l;
+  Changed.apply()
+
 let add_spec ?register_children ?(force=false) e kf ?stmt ?active spec =
   let full_spec = get_spec_all kf ?stmt ?active () in
   let conflicts =
@@ -1228,20 +1311,22 @@ let add_spec ?register_children ?(force=false) e kf ?stmt ?active spec =
      | _ -> [])
   in
   if not force && conflicts <> [] then raise (AlreadySpecified conflicts) ;
-  add_behaviors ?register_children e kf ?stmt ?active spec.spec_behavior;
+  do_add_behaviors ?register_children e kf ?stmt ?active spec.spec_behavior;
   Option.iter
-    (fun variant -> add_decreases ~force e kf variant)
+    (fun variant -> do_add_decreases ~force e kf variant)
     spec.spec_variant;
   Option.iter
-    (fun terminates -> add_terminates ~force e kf ?stmt ?active terminates)
+    (fun terminates -> do_add_terminates ~force e kf ?stmt ?active terminates)
     spec.spec_terminates;
   List.iter
-    (fun complete -> add_complete e kf ?stmt ?active complete)
+    (fun complete -> do_add_complete e kf ?stmt ?active complete)
     spec.spec_complete_behaviors;
   List.iter
-    (fun disjoint -> add_disjoint e kf ?stmt ?active disjoint)
-    spec.spec_disjoint_behaviors
+    (fun disjoint -> do_add_disjoint e kf ?stmt ?active disjoint)
+    spec.spec_disjoint_behaviors;
+  Changed.apply()
 
+(* internal use only *)
 let extend_behavior
     e kf ?stmt ?active ?(behavior=Cil.default_behavior_name) set_bhv =
   (* Kernel.feedback "Function %a, behavior %s" Kf.pretty kf bhv_name;*)
@@ -1263,7 +1348,8 @@ let extend_behavior
   Property_status.remove ip;
   set_bhv b b';
   let ip = Property.ip_of_behavior kf (kinstr stmt) ~active b in
-  Property_status.register ip
+  Property_status.register ip;
+  Changed.apply()
 
 let add_requires e kf ?stmt ?active ?behavior l =
   let set_bhv _ bhv =
@@ -1397,7 +1483,8 @@ let add_extended e kf ?stmt ?active ?behavior ext =
 
 (** {3 Adding code annotations} *)
 
-let add_code_annot ?(keep_empty=true) emitter ?kf stmt ca =
+(* internal use only *)
+let do_add_code_annot ~keep_empty emitter ?kf stmt ca =
   (*  Kernel.feedback "%a: adding code annot %a with stmt %a (%d)"
       Project.pretty (Project.current ())
       Code_annotation.pretty ca
@@ -1442,18 +1529,18 @@ let add_code_annot ?(keep_empty=true) emitter ?kf stmt ca =
      | [ { annot_content = AStmtSpec _ } ] ->
        let register_children = true in
        let active = bhvs in
-       add_behaviors
+       do_add_behaviors
          ~register_children emitter kf ~stmt ~active spec.spec_behavior;
        if spec.spec_variant <> None then
          Kernel.fatal
            "statement contract cannot have a decrease clause";
        Option.iter
-         (add_terminates emitter kf ~stmt ~active) spec.spec_terminates;
+         (do_add_terminates emitter kf ~stmt ~active) spec.spec_terminates;
        List.iter
-         (add_complete emitter kf ~stmt ~active)
+         (do_add_complete emitter kf ~stmt ~active)
          spec.spec_complete_behaviors;
        List.iter
-         (add_disjoint emitter kf ~stmt ~active)
+         (do_add_disjoint emitter kf ~stmt ~active)
          spec.spec_disjoint_behaviors;
        (* By construction, we have exactly one contract
           corresponding to our criterion and emitter. *)
@@ -1557,6 +1644,10 @@ let add_code_annot ?(keep_empty=true) emitter ?kf stmt ca =
   | APragma _ | AExtended _ ->
     fill_tables ca (Property.ip_of_code_annot kf stmt ca)
 
+let add_code_annot ?(keep_empty=true) emitter ?kf stmt ca =
+  do_add_code_annot ~keep_empty emitter ?kf stmt ca;
+  Changed.apply()
+
 let add_assert e ?kf stmt a =
   let a = Logic_const.toplevel_predicate ~kind:Assert a in
   let a = Logic_const.new_code_annotation (AAssert ([],a)) in
@@ -1654,7 +1745,8 @@ let add_model_field e m =
     try Emitter.Usable_emitter.Hashtbl.find h e
     with Not_found -> []
   in
-  Emitter.Usable_emitter.Hashtbl.replace h e (m::l)
+  Emitter.Usable_emitter.Hashtbl.replace h e (m::l);
+  Changed.apply()
 
 let unsafe_add_global e a =
   (*  Kernel.feedback "adding global %a in project %a"
@@ -1669,7 +1761,8 @@ let unsafe_add_global e a =
 
 let add_global e a =
   unsafe_add_global e a;
-  if Ast.is_computed() then insert_global_in_ast a
+  if Ast.is_computed() then insert_global_in_ast a;
+  Changed.apply()
 
 (**************************************************************************)
 (** {2 Other useful functions} *)
@@ -1766,7 +1859,9 @@ let code_annot_of_kf kf = match kf.fundec with
 
 (* don't export the possibility to removing an annotation without associated
    statuses. This is purely internal. *)
-let remove_code_annot e ?kf stmt ca = remove_code_annot_internal e ?kf stmt ca
+let remove_code_annot e ?kf stmt ca =
+  remove_code_annot_internal e ?kf stmt ca;
+  Changed.apply()
 
 (*
   Local Variables:
diff --git a/src/kernel_services/ast_data/annotations.mli b/src/kernel_services/ast_data/annotations.mli
index 3d84adb429de8fd69bd5644009a5b8a062b515df..f05e3dececf4db420c5163b7595a344c15779a65 100644
--- a/src/kernel_services/ast_data/annotations.mli
+++ b/src/kernel_services/ast_data/annotations.mli
@@ -30,6 +30,10 @@ open Cil_types
 (** {2 Getting annotations} *)
 (**************************************************************************)
 
+val add_hook_on_change: (unit -> unit) -> unit
+(** Emitted whenever any of the annotation tables is modified.
+    @since 27.0-Cobalt *)
+
 (**************************************************************************)
 (** {3 Code annotations} *)
 (**************************************************************************)
diff --git a/src/kernel_services/ast_data/cil_types.ml b/src/kernel_services/ast_data/cil_types.ml
index 21a599460d2fdb73bd81e6e805e3c075424be978..d603249ae2e308282a4f99c8a8e619c36ea3f7b9 100644
--- a/src/kernel_services/ast_data/cil_types.ml
+++ b/src/kernel_services/ast_data/cil_types.ml
@@ -1836,27 +1836,31 @@ type kernel_function = {
   mutable spec : funspec;
 }
 
-(* [VP] TODO: VLocal should be attached to a particular block, not a whole
-   function. It might be worth it to unify this type with the newer
-   syntactic_scope below.
-*)
-type localisation =
-  | VGlobal
-  | VLocal of kernel_function
-  | VFormal of kernel_function
-
 (** Various syntactic scopes through which an identifier might be searched.
     Note that for this purpose static variables are still tied to the block
     where they were declared in the original source (see {!Cil_types.block}).
     @since Chlorine-20180501
 *)
 type syntactic_scope =
+  | Global
+  (** Any global symbol, whether static or not.
+      @since 27.0-Cobalt
+  *)
   | Program (** Only non-static global symbols. *)
   | Translation_unit of Filepath.Normalized.t
   (** Any global visible within the given C source file. *)
+  | Formal of kernel_function
+  (** formal parameter of the given function.
+      @since 27.0-Cobalt
+  *)
   | Block_scope of stmt
-  (** same as above + all locals of the blocks to which the given statement
+  (** locals (including static locals) of the block to which the given statement
       belongs. *)
+  | Whole_function of kernel_function
+  (** same as above, but any local variable of the given function, regardless of
+      the block to which it is tied, will be considered.
+      @since 27.0-Cobalt
+  *)
 
 (** Definition of a machine model (architecture + compiler).
     @see <https://frama-c.com/download/frama-c-plugin-development-guide.pdf> Plug-in Development Guide *)
@@ -1872,8 +1876,22 @@ type mach = {
   sizeof_void: int;       (* Size of "void" *)
   sizeof_fun: int;        (* Size of function. Negative if unsupported. *)
   size_t: string;         (* Type of "sizeof(T)" *)
+  ssize_t: string;        (* representation of ssize_t *)
   wchar_t: string;        (* Type of "wchar_t" *)
   ptrdiff_t: string;      (* Type of "ptrdiff_t" *)
+  intptr_t: string;       (* Type of "intptr_t" *)
+  uintptr_t: string;      (* Type of "uintptr_t" *)
+  int_fast8_t: string;     (* Type of "int_fast8_t" *)
+  int_fast16_t: string;     (* Type of "int_fast16_t" *)
+  int_fast32_t: string;     (* Type of "int_fast32_t" *)
+  int_fast64_t: string;     (* Type of "int_fast64_t" *)
+  uint_fast8_t: string;     (* Type of "uint_fast8_t" *)
+  uint_fast16_t: string;     (* Type of "uint_fast16_t" *)
+  uint_fast32_t: string;     (* Type of "uint_fast32_t" *)
+  uint_fast64_t: string;     (* Type of "uint_fast64_t" *)
+  wint_t: string;          (* Type of "wint_t" *)
+  sig_atomic_t: string;   (* Type of "sig_atomic_t" *)
+  time_t: string;          (* Type of "time_t" *)
   alignof_short: int;     (* Alignment of "short" *)
   alignof_int: int;       (* Alignment of "int" *)
   alignof_long: int;      (* Alignment of "long" *)
@@ -1885,8 +1903,6 @@ type mach = {
   alignof_str: int;       (* Alignment of strings *)
   alignof_fun: int;       (* Alignment of function. Negative if unsupported. *)
   char_is_unsigned: bool; (* Whether "char" is unsigned *)
-  underscore_name: bool;  (* If assembly names have leading underscore *)
-  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 *);
   has__builtin_va_list: bool (* Whether [__builtin_va_list] is a known type *);
@@ -1895,6 +1911,24 @@ type mach = {
   cpp_arch_flags: string list;  (* Architecture-specific flags to be given to
                                    the preprocessor (if supported) *)
   version: string;        (* Information on this machdep *)
+  weof: string; (* expansion of WEOF macro, empty if undefined *)
+  wordsize: string; (* expansion of __WORDSIZE macro, empty if undefined *)
+  posix_version: string; (* expansion of _POSIX_VERSION macro, empty if undefined *)
+  bufsiz: string; (* expansion of BUFSIZ macro *)
+  eof: string; (* expansion of EOF macro *)
+  fopen_max: string; (* expansion of FOPEN_MAX macro *)
+  filename_max: string; (* expansion of FILENAME_MAX macro *)
+  host_name_max: string; (* expansion of HOST_NAME_MAX macro *)
+  tty_name_max: string; (* expansion of TTY_NAME_MAX macro *)
+  l_tmpnam: string; (* expansion of L_tmpnam macro *)
+  path_max: string; (* expansion of PATH_MAX macro *)
+  tmp_max: string; (* expansion of TMP_MAX macro *)
+  rand_max: string; (* expansion of RAND_MAX macro *)
+  mb_cur_max: string; (* expansion of MB_CUR_MAX macro *)
+  nsig: string; (* expansion of non-standard NSIG macro, empty if undefined *)
+  errno: (string * string) list; (* list of macros defining errors in errno.h*)
+  machdep_name: string; (* name of the machdep *)
+  custom_defs: string; (* arbitrary text to be written in the header *)
 }
 
 (*
diff --git a/src/kernel_services/ast_data/globals.ml b/src/kernel_services/ast_data/globals.ml
index 42b251943f4224c468d6d214c88d10aa91f1dcd4..4211f7a067776bf54e2f4dc46c3d19f18713bbf7 100644
--- a/src/kernel_services/ast_data/globals.ml
+++ b/src/kernel_services/ast_data/globals.ml
@@ -43,6 +43,8 @@ let get_locals f = match f.fundec with
 let get_location kf = match kf.fundec with
   | Definition (_, loc) | Declaration (_,_,_, loc) -> loc
 
+let get_statics = Extlib.mk_fun "Globals.get_statics"
+
 let find_first_stmt = Extlib.mk_fun "Globals.find_first_stmt"
 
 let find_enclosing_block = Extlib.mk_fun "Globals.find_enclosing_block"
@@ -73,21 +75,40 @@ module Vars = struct
 
   let add_decl vi = add vi { init = None }
 
-  let get_astinfo_ref : (Cil_types.varinfo -> string * localisation) ref =
+  let get_astinfo_ref : (Cil_types.varinfo -> string * syntactic_scope) ref =
     Extlib.mk_fun "get_astinfo_ref"
 
   exception Found of varinfo
-  let find_from_astinfo name = function
-    | VGlobal ->
+  let find_from_astinfo name scope =
+    let iter_glob cond =
+      try
+        iter (fun v _ -> if cond v then raise (Found v));
+        raise Not_found
+      with Found v -> v
+    in
+    match scope with
+    | Global -> iter_glob (fun v -> v.vname = name)
+    | Program ->
+      iter_glob (fun v -> v.vname = name && not (v.vstorage = Static))
+    | Translation_unit file ->
+      iter_glob
+        (fun v ->
+           v.vname = name &&
+           Filepath.Normalized.equal file (fst v.vdecl).pos_path)
+    | Whole_function kf ->
+      List.find (fun v -> v.vname = name) (get_locals kf @ !get_statics kf)
+    | Formal kf ->
+      List.find (fun v -> v.vname = name) (get_formals kf)
+    | Block_scope stmt ->
+      let blocks = !find_all_enclosing_blocks stmt in
       (try
-         iter (fun v _ -> if v.vname = name then raise (Found v));
+         List.iter
+           (fun b ->
+              (List.iter (fun v -> if v.vname = name then raise (Found v))
+                 (b.blocals @ b.bstatics)))
+           blocks;
          raise Not_found
-       with Found v ->
-         v)
-    | VLocal kf ->
-      List.find (fun v -> v.vname = name) (get_locals kf)
-    | VFormal kf ->
-      List.find (fun v -> v.vname = name) (get_formals kf)
+       with Found v -> v)
 
   let get_astinfo vi = !get_astinfo_ref vi
 
@@ -394,7 +415,12 @@ module Functions = struct
   exception Found of kernel_function
   let get_astinfo vi =
     vi.vname,
-    if vi.vglob then VGlobal
+    if vi.vglob then begin
+      if vi.vstorage = Static then
+        Translation_unit (fst vi.vdecl).pos_path
+      else
+        Program
+    end
     else begin
       if vi.vformal then begin
         try
@@ -404,7 +430,7 @@ module Functions = struct
                then raise (Found kf));
           assert false
         with Found kf ->
-          VFormal kf
+          Formal kf
       end else begin
         try
           iter
@@ -413,7 +439,8 @@ module Functions = struct
                then raise (Found kf));
           assert false
         with Found kf ->
-          VLocal kf
+          (* TODO: find the block where the varinfo is defined. *)
+          Whole_function kf
       end
     end
 
@@ -622,8 +649,8 @@ end
 module Syntactic_search = struct
 
   module Key =
-    Datatype.Pair_with_collections
-      (Datatype.String)(Cil_datatype.Syntactic_scope)
+    Datatype.Triple_with_collections
+      (Datatype.String)(Cil_datatype.Syntactic_scope)(Datatype.Bool)
       (struct let module_name = "Globals.Datatype.Key" end)
 
   module Scope_info =
@@ -639,23 +666,40 @@ module Syntactic_search = struct
 
   let () = Ast.add_monotonic_state self
 
-  let rec find_var (x,scope) =
+  let rec find_var (x,scope,strict) =
     let has_name v = v.vorig_name = x in
     let global_has_name v =
       has_name v && v.vglob
       && not (Cil.hasAttribute Cabs2cil.fc_local_static v.vattr)
     in
+    let lookup next_scope candidate =
+      match candidate with
+      | Some _ -> candidate
+      | None when strict -> candidate
+      | None -> find_in_scope x next_scope
+    in
     let module M = struct exception Found of varinfo end in
     match scope with
+    | Global ->
+      (try
+         Vars.iter (fun v _ -> if has_name v then raise (M.Found v));
+         None
+       with M.Found v -> Some v)
     | Program ->
       (try
          Vars.iter (fun v _ -> if global_has_name v then raise (M.Found v));
          None
        with M.Found v -> Some v)
     | Translation_unit file ->
-      let symbols = FileIndex.get_globals file in
-      (try Some (fst (List.find (fun x -> (global_has_name (fst x))) symbols))
-       with Not_found -> find_in_scope x Program)
+      let symbols,_ = List.split (FileIndex.get_globals file) in
+      List.find_opt global_has_name symbols |> lookup Program
+    | Formal kf ->
+      let file = (fst (get_location kf)).Filepath.pos_path in
+      List.find_opt has_name (get_formals kf) |>
+      lookup (Translation_unit file)
+    | Whole_function kf ->
+      List.find_opt has_name (get_locals kf @ !get_statics kf) |>
+      lookup (Formal kf)
     | Block_scope stmt ->
       let blocks = !find_all_enclosing_blocks stmt in
       let find_in_block b =
@@ -665,17 +709,19 @@ module Syntactic_search = struct
           raise (M.Found (List.find has_name b.bstatics))
       in
       try
-        List.iter find_in_block blocks;
-        let kf = !find_englobing_kf stmt in
-        let filename = (fst ( get_location kf)).Filepath.pos_path in
-        let formals = get_formals kf in
-        if List.exists has_name formals then
-          Some (List.find has_name formals)
+        (* blocks can't be empty, we have at least the body of the function. *)
+        find_in_block (List.hd blocks);
+        if strict then None
         else
-          find_in_scope x (Translation_unit filename)
+          begin
+            List.iter find_in_block (List.tl blocks);
+            let kf = !find_englobing_kf stmt in
+            if strict then None else find_in_scope x (Formal kf)
+          end
       with M.Found v -> Some v
 
-  and find_in_scope x scope = Scope_info.memo find_var (x,scope)
+  and find_in_scope ?(strict=false) x scope =
+    Scope_info.memo find_var (x,scope,strict)
 
 end
 
diff --git a/src/kernel_services/ast_data/globals.mli b/src/kernel_services/ast_data/globals.mli
index 51ff3e98930da8c361f16d549623fce442cbbc93..82c52f193756bb583247a554bfb034ba90a218e4 100644
--- a/src/kernel_services/ast_data/globals.mli
+++ b/src/kernel_services/ast_data/globals.mli
@@ -35,7 +35,7 @@ module Vars: sig
 
   val find: varinfo -> initinfo
 
-  val find_from_astinfo: string -> localisation -> varinfo
+  val find_from_astinfo: string -> syntactic_scope -> varinfo
   (** Finds a variable from its [vname] according to its localisation (which
       might be a local). If you wish to search for a symbol according to its
       original name in the source code and the syntactic scope in which
@@ -43,7 +43,7 @@ module Vars: sig
       @raise Not_found if no such variable exists.
   *)
 
-  val get_astinfo: varinfo -> string * localisation
+  val get_astinfo: varinfo -> string * syntactic_scope
   (** Linear in the number of locals and formals of the program. *)
 
   (** {2 Iterators} *)
@@ -221,13 +221,24 @@ end
 module Syntactic_search: sig
   val self: State.t
 
-  val find_in_scope: string -> syntactic_scope -> varinfo option
+  val find_in_scope: ?strict:bool -> string -> syntactic_scope -> varinfo option
   (** [find_in_scope orig_name scope] finds a variable from its [orig_name],
       according to the syntactic [scope] in which it should be searched.
+      @param strict indicates whether the symbol should be searched only in
+        the exact [scope] that it is given. It defaults to [false], meaning
+        that the search will look for enclosing scopes, according to C lookup
+        rules. More precisely, non-strict lookup will proceed according to the
+        following order: [Block_scope] will move across all enclosing blocks
+        up to the function body (or all locals will be searched directly in
+        case of [Whole_function]). Then, [Formal] will be considered, followed
+        by [Translation_unit] (for the file where the function is defined),
+        then [Program].
       @return [None] if there are no variables [orig_name] in [scope].
       @return [Some vi] otherwise, with [vi] the [varinfo] associated to
-      [orig_name] in [scope] according to C lookup rules.
+        [orig_name] in [scope] (or an enclosing scope when [strict] is false).
       @since Chlorine-20180501
+      @before 27.0-Cobalt [strict] parameter did not exist, symbol was always
+        searched according to C lookup rules.
   *)
 end
 
@@ -338,6 +349,7 @@ val get_comments_stmt: stmt -> string list
 (* Forward reference to functions defined in Kernel_function. Do not
    use outside of this module.
 *)
+val get_statics: (kernel_function -> varinfo list) ref
 val find_first_stmt: (kernel_function -> stmt) ref
 val find_enclosing_block: (stmt -> block) ref
 val find_all_enclosing_blocks: (stmt -> block list) ref
diff --git a/src/kernel_services/ast_data/kernel_function.ml b/src/kernel_services/ast_data/kernel_function.ml
index be29ec2b73fb94bc4a0bbdb433efd413e7d7e80f..1776d39211ec7d2ca18590947e62c903d807ce6f 100644
--- a/src/kernel_services/ast_data/kernel_function.ml
+++ b/src/kernel_services/ast_data/kernel_function.ml
@@ -67,6 +67,8 @@ let get_statics f = match f.fundec with
     !statics
   | Declaration (_, _, _, _) -> []
 
+let () = Globals.get_statics := get_statics
+
 exception No_Definition
 let get_definition kf = match kf.fundec with
   | Definition (f,_) -> f
diff --git a/src/kernel_services/ast_data/property_status.mli b/src/kernel_services/ast_data/property_status.mli
index bddc3ea1c9f4eeb4ff36ebd51e744bdeb225e1e7..f25ccdcc65bd7e33052bdb2314dcd18be59f0211 100644
--- a/src/kernel_services/ast_data/property_status.mli
+++ b/src/kernel_services/ast_data/property_status.mli
@@ -141,7 +141,7 @@ val fold_on_statuses:
 val register_status_update_hook:
   (emitter_with_properties -> Property.t -> emitted_status -> unit) -> unit
 (** Registers an hook to be called each time a property status is emitted.
-    @since Frama-C+dev *)
+    @since 27.0-Cobalt *)
 
 (* ************************************************************************ *)
 (** {2 Consolidated status} *)
diff --git a/src/kernel_services/ast_printing/cil_printer.ml b/src/kernel_services/ast_printing/cil_printer.ml
index cd8d3806d7e91d1f1fc4bd7d8213b8bb832abb99..7301e2f5ed22d72161b128129b352cb24a83dfd0 100644
--- a/src/kernel_services/ast_printing/cil_printer.ml
+++ b/src/kernel_services/ast_printing/cil_printer.ml
@@ -2530,20 +2530,22 @@ class cil_printer () = object (self)
       fprintf fmt "@[%a@]" self#tand_list (get_tand_list l [r])
     | TBinOp (op,l,r) ->
       fprintf fmt "@[%a@ %a@ %a@]" term l self#term_binop op term r
-    | TCastE (ty,e) ->
+    | TCastE (ty,t) ->
       begin match ty, t.term_node with
         | TFloat(fk,_) , TConst(LReal r as cst) when
             not Kernel.(is_debug_key_enabled dkey_print_logic_coercions) &&
             Floating_point.has_suffix fk r.r_literal ->
           self#logic_constant fmt cst
         | _ ->
-          fprintf fmt "(%a)%a" (self#typ None) ty term e
+          fprintf fmt "(%a)%a" (self#typ None) ty term t
       end
     | TAddrOf lv ->
       fprintf fmt "&%a" (self#term_lval_prec Precedence.addrOfLevel) lv
-    | TStartOf lv -> fprintf fmt "(%a)%a"
-                       (self#logic_type None) t.term_type
-                       (self#term_lval_prec current_level) lv
+    | TStartOf lv ->
+      let typ = Logic_utils.array_to_ptr (Cil.typeOfTermLval lv) in
+      fprintf fmt "(%a)%a"
+        (self#logic_type None) typ
+        (self#term_lval_prec current_level) lv
     (* A few built-ins for lists have special syntax. Use it when we're not
        in print-as-is mode. *)
     | Tapp ({ l_var_info },[],[e1; e2])
@@ -3435,6 +3437,12 @@ let () = Cil.pp_lval_ref := pp_lval
 let () = Cil.pp_ikind_ref := pp_ikind
 let () = Cil.pp_attribute_ref := pp_attribute
 let () = Cil.pp_attributes_ref := pp_attributes
+let () = Cil.pp_term_ref := pp_term
+let () = Cil.pp_logic_type_ref := pp_logic_type
+let () = Cil.pp_identified_term_ref := pp_identified_term
+let () = Cil.pp_location_ref := pp_location
+let () = Cil.pp_from_ref := pp_from
+let () = Cil.pp_behavior_ref := pp_behavior
 
 (*
 Local Variables:
diff --git a/src/kernel_services/ast_printing/cil_types_debug.ml b/src/kernel_services/ast_printing/cil_types_debug.ml
index 052943406bf0f43ed5cde2c2c43c2cbb2e5e632c..97cbc21081fba3d4763edac53f4ed9bf1f68c882 100644
--- a/src/kernel_services/ast_printing/cil_types_debug.ml
+++ b/src/kernel_services/ast_printing/cil_types_debug.ml
@@ -1035,10 +1035,15 @@ let pp_kernel_function fmt kernel_function =
     pp_cil_function kernel_function.fundec
     pp_funspec kernel_function.spec
 
-let pp_localisation fmt = function
-  | VGlobal -> Format.fprintf fmt "VGlobal"
-  | VLocal(kernel_function) -> Format.fprintf fmt "VLocal(%a)"  pp_kernel_function kernel_function
-  | VFormal(kernel_function) -> Format.fprintf fmt "VFormal(%a)"  pp_kernel_function kernel_function
+let pp_syntactic_scope fmt = function
+  | Global -> pp_string fmt "Global"
+  | Program -> pp_string fmt "Program"
+  | Translation_unit file ->
+    Format.fprintf fmt "Translation_unit %S" (file:>string)
+  | Formal kf -> Format.fprintf fmt "Formal %a" pp_kernel_function kf
+  | Block_scope stmt -> Format.fprintf fmt "Local %a" pp_stmt stmt
+  | Whole_function kf ->
+    Format.fprintf fmt "Whole_function %a" pp_kernel_function kf
 
 let pp_mach fmt mach =
   Format.fprintf fmt
@@ -1047,8 +1052,8 @@ let pp_mach fmt mach =
      sizeof_void=%a;sizeof_fun=%a;size_t=%a;wchar_t=%a;ptrdiff_t=%a;\
      alignof_short=%a;alignof_int=%a;alignof_long=%a;alignof_longlong=%a;\
      alignof_ptr=%a;alignof_float=%a;alignof_double=%a;alignof_longdouble=%a;\
-     alignof_str=%a;alignof_fun=%a;char_is_unsigned=%a;underscore_name=%a;\
-     const_string_literals=%a;little_endian=%a;alignof_aligned=%a;\
+     alignof_str=%a;alignof_fun=%a;char_is_unsigned=%a;\
+     little_endian=%a;alignof_aligned=%a;\
      has__builtin_va_list=%a;compiler=%a;\
      cpp_arch_flags=%a;version=%a}"
     pp_int mach.sizeof_short
@@ -1075,8 +1080,6 @@ let pp_mach fmt mach =
     pp_int mach.alignof_str
     pp_int mach.alignof_fun
     pp_bool mach.char_is_unsigned
-    pp_bool mach.underscore_name
-    pp_bool mach.const_string_literals
     pp_bool mach.little_endian
     pp_int mach.alignof_aligned
     pp_bool mach.has__builtin_va_list
diff --git a/src/kernel_services/ast_printing/cil_types_debug.mli b/src/kernel_services/ast_printing/cil_types_debug.mli
index cf447e2ad48636736196b54fe87b81f6bb754aef..e9d3c6fb74aa75dd700d3ed7812ad0406449817a 100644
--- a/src/kernel_services/ast_printing/cil_types_debug.mli
+++ b/src/kernel_services/ast_printing/cil_types_debug.mli
@@ -157,5 +157,5 @@ val pp_global_annotation : Cil_types.global_annotation Pretty_utils.formatter
 val pp_kinstr : Format.formatter -> Cil_types.kinstr -> unit
 val pp_cil_function : Format.formatter -> Cil_types.cil_function -> unit
 val pp_kernel_function : Format.formatter -> Cil_types.kernel_function -> unit
-val pp_localisation : Format.formatter -> Cil_types.localisation -> unit
+val pp_syntactic_scope: Format.formatter -> Cil_types.syntactic_scope -> unit
 val pp_mach : Format.formatter -> Cil_types.mach -> unit
diff --git a/src/kernel_services/ast_queries/ast_diff.ml b/src/kernel_services/ast_queries/ast_diff.ml
index de58f03133ae3fbc11682cd552b454bbed0b12ec..222d4c77a26e2b10ba247b08b698d63ff7a6b886 100644
--- a/src/kernel_services/ast_queries/ast_diff.ml
+++ b/src/kernel_services/ast_queries/ast_diff.ml
@@ -1388,7 +1388,7 @@ and enumitem_correspondence ?loc ei env =
 
 and gvar_correspondence ?loc vi env =
   let add vi =
-    match find_candidate_varinfo ?loc vi Cil_types.VGlobal with
+    match find_candidate_varinfo ?loc vi Cil_types.Global with
     | None when Cil.isFunctionType vi.vtype ->
       begin
         match gfun_correspondence ?loc vi env with
diff --git a/src/kernel_services/ast_queries/cil.ml b/src/kernel_services/ast_queries/cil.ml
index c37a95eb29a7ee764725c4da4210b2e892c424d4..d5a6b27c12b79ccb5cd9734b8c2f9e42164efc67 100644
--- a/src/kernel_services/ast_queries/cil.ml
+++ b/src/kernel_services/ast_queries/cil.ml
@@ -105,7 +105,6 @@ type theMachine =
     mutable lowerConstants: bool; (** Do lower constants (default true) *)
     mutable insertImplicitCasts: bool; (** Do insert implicit casts
                                            (default true) *)
-    mutable underscore_name: bool;
     mutable stringLiteralType: typ;
     mutable upointKind: ikind;
     mutable upointType: typ;
@@ -120,11 +119,10 @@ type theMachine =
 
 let createMachine () = (* Contain dummy values *)
   { useLogicalOperators = false;
-    theMachine = Machdeps.x86_64;
+    theMachine = List.hd Cil_datatype.Machdep.reprs;
     lowerConstants = false(*true*);
     insertImplicitCasts = true;
-    underscore_name = true;
-    stringLiteralType = charPtrType;
+    stringLiteralType = charConstPtrType;
     upointKind = IChar;
     upointType = voidType;
     wcharKind = IChar;
@@ -140,7 +138,6 @@ let copyMachine src dst =
   dst.theMachine <- src.theMachine;
   dst.lowerConstants <- src.lowerConstants;
   dst.insertImplicitCasts <- src.insertImplicitCasts;
-  dst.underscore_name <- src.underscore_name;
   dst.stringLiteralType <- src.stringLiteralType;
   dst.upointKind <- src.upointKind;
   dst.upointType <- src.upointType;
@@ -234,6 +231,12 @@ let pp_lval_ref = Extlib.mk_fun "Cil.pp_lval_ref"
 let pp_ikind_ref = Extlib.mk_fun "Cil.pp_ikind_ref"
 let pp_attribute_ref = Extlib.mk_fun "Cil.pp_attribute_ref"
 let pp_attributes_ref = Extlib.mk_fun "Cil.pp_attributes_ref"
+let pp_term_ref = Extlib.mk_fun "Cil.pp_term_ref"
+let pp_logic_type_ref = Extlib.mk_fun "Cil.pp_logic_type_ref"
+let pp_identified_term_ref = Extlib.mk_fun "Cil.pp_identified_term_ref"
+let pp_location_ref = Extlib.mk_fun "Cil.pp_location_ref"
+let pp_from_ref = Extlib.mk_fun "Cil.pp_from_ref"
+let pp_behavior_ref = Extlib.mk_fun "Cil.pp_behavior_ref"
 
 let default_behavior_name = "default!"
 let is_default_mk_behavior ~name ~assumes = name = default_behavior_name && assumes =[]
@@ -3689,7 +3692,9 @@ let rec typeOf (e: exp) : typ =
    * have SizeOfStr for that *)
   | Const(CStr _s) -> theMachine.stringLiteralType
 
-  | Const(CWStr _s) -> TPtr(theMachine.wcharType,[])
+  | Const(CWStr _s) ->
+    let typ = typeAddAttributes [Attr("const",[])] theMachine.wcharType in
+    TPtr(typ,[])
 
   | Const(CReal (_, fk, _)) -> TFloat(fk, [])
 
@@ -6408,9 +6413,7 @@ let initCIL ~initLogicBuiltins machdep =
     (* Set the machine *)
     theMachine.theMachine <- machdep;
     (* Pick type for string literals *)
-    theMachine.stringLiteralType <-
-      if theMachine.theMachine.const_string_literals then charConstPtrType
-      else charPtrType;
+    theMachine.stringLiteralType <- charConstPtrType;
     (* Find the right ikind given the size *)
     let findIkindSz (unsigned: bool) (sz: int) : ikind =
       (* Test the most common sizes first *)
@@ -6453,8 +6456,6 @@ let initCIL ~initLogicBuiltins machdep =
     theMachine.wcharType <- TInt(theMachine.wcharKind, []);
     theMachine.ptrdiffKind <- findIkindName theMachine.theMachine.ptrdiff_t;
     theMachine.ptrdiffType <- TInt(theMachine.ptrdiffKind, []);
-    theMachine.underscore_name <-
-      theMachine.theMachine.Cil_types.underscore_name;
     theMachine.useLogicalOperators <- Kernel.LogicalOperators.get() (* do not use lazy LAND and LOR *);
     (*nextGlobalVID <- 1 ;
       nextCompinfoKey <- 1;*)
diff --git a/src/kernel_services/ast_queries/cil.mli b/src/kernel_services/ast_queries/cil.mli
index e72b94b9228cff384ad8d91edf0ca53139097053..8b63fb51b24e9a757822fd9696bd9c9b00902fcc 100644
--- a/src/kernel_services/ast_queries/cil.mli
+++ b/src/kernel_services/ast_queries/cil.mli
@@ -70,10 +70,6 @@ type theMachine = private
     mutable lowerConstants: bool; (** Do lower constants (default true) *)
     mutable insertImplicitCasts: bool;
     (** Do insert implicit casts (default true) *)
-    mutable underscore_name: bool;
-    (** Whether the compiler generates assembly labels by prepending "_" to
-        the identifier. That is, will function foo() have the label "foo", or
-        "_foo"? *)
     mutable stringLiteralType: typ;
     mutable upointKind: ikind
   (** An unsigned integer type that fits pointers. *);
@@ -436,7 +432,7 @@ val isCompleteType: ?allowZeroSizeArrays:bool -> typ -> bool
 (** Performs lvalue-conversion on the type and returns the converted type,
     or Error if the type is incomplete and not an array type.
 
-    @since Frama-C+dev
+    @since 27.0-Cobalt
 *)
 val lvalue_conversion: typ -> (typ, string) result
 
@@ -2362,6 +2358,12 @@ val pp_lval_ref: (Format.formatter -> lval -> unit) ref
 val pp_ikind_ref: (Format.formatter -> ikind -> unit) ref
 val pp_attribute_ref: (Format.formatter -> attribute -> unit) ref
 val pp_attributes_ref: (Format.formatter -> attribute list -> unit) ref
+val pp_term_ref: (Format.formatter -> term -> unit) ref
+val pp_logic_type_ref: (Format.formatter -> logic_type -> unit) ref
+val pp_identified_term_ref: (Format.formatter -> identified_term -> unit) ref
+val pp_location_ref: (Format.formatter -> location -> unit) ref
+val pp_from_ref: (Format.formatter -> from -> unit) ref
+val pp_behavior_ref: (Format.formatter -> behavior -> unit) ref
 
 val set_extension_handler:
   visit:(string -> cilVisitor -> acsl_extension_kind ->
diff --git a/src/kernel_services/ast_queries/cil_datatype.ml b/src/kernel_services/ast_queries/cil_datatype.ml
index 25c688a55d5671f268e68b266802a810db6ff9dc..ffd2febd6b3814af4e9a5c30012b4916ddc88e1c 100644
--- a/src/kernel_services/ast_queries/cil_datatype.ml
+++ b/src/kernel_services/ast_queries/cil_datatype.ml
@@ -2579,16 +2579,6 @@ module Lexpr = Make
 (** {3 Other types} *)
 (**************************************************************************)
 
-module Localisation =
-  Datatype.Make
-    (struct
-      include Datatype.Serializable_undefined
-      type t = localisation
-      let name = "Localisation"
-      let reprs = [ VGlobal ]
-      let mem_project = Datatype.never_any_project
-    end)
-
 module Syntactic_scope =
   Datatype.Make_with_collections
     (struct
@@ -2598,6 +2588,9 @@ module Syntactic_scope =
       let reprs = [ Program ]
       let compare s1 s2 =
         match s1, s2 with
+        | Global, Global -> 0
+        | Global, _ -> 1
+        | _, Global -> -1
         | Program, Program -> 0
         | Program, _ -> 1
         | _, Program -> -1
@@ -2605,22 +2598,117 @@ module Syntactic_scope =
           Datatype.Filepath.compare s1 s2
         | Translation_unit _, _ -> 1
         | _, Translation_unit _ -> -1
+        | Formal kf1, Formal kf2 -> Kf.compare kf1 kf2
+        | Formal _, _ -> 1
+        | _, Formal _ -> -1
+        | Whole_function kf1, Whole_function kf2 -> Kf.compare kf1 kf2
+        | Whole_function _, _ -> 1
+        | _, Whole_function _ -> -1
         | Block_scope s1, Block_scope s2 -> Stmt_Id.compare s1 s2
       let equal = Datatype.from_compare
       let hash s =
         match s with
+        | Global -> 3
         | Program -> 5
         | Translation_unit s -> 7 * Datatype.Filepath.hash s + 11
         | Block_scope s -> 13 * Stmt_Id.hash s  + 17
+        | Whole_function kf -> 19 * Kf.hash kf + 23
+        | Formal kf -> 29 * Kf.hash kf + 31
       let pretty fmt = function
-        | Program -> Format.pp_print_string fmt "<Whole Program>"
+        | Global | Program -> Format.pp_print_string fmt "<Whole Program>"
         | Translation_unit s ->
           Format.fprintf fmt "File %a" Datatype.Filepath.pretty s
+        | Formal kf ->
+          Format.fprintf fmt "Parameter of %a" Kf.pretty kf
+        | Whole_function kf ->
+          Format.fprintf fmt "Local variable of %a" Kf.pretty kf
         | Block_scope s ->
           Format.fprintf fmt "Statement at %a:@\n@[%a@]"
             Location.pretty (Stmt.loc s) Stmt.pretty s
     end)
 
+let dummy_machdep =
+  {
+    sizeof_short = 2;
+    sizeof_int = 4;
+    sizeof_long = 8;
+    sizeof_longlong = 8;
+    sizeof_ptr = 8;
+    sizeof_float = 4;
+    sizeof_double = 8;
+    sizeof_longdouble = 16;
+    sizeof_void = -1;
+    sizeof_fun = -1;
+    size_t = "unsigned long";
+    ssize_t = "long";
+    wchar_t = "int";
+    ptrdiff_t = "long";
+    intptr_t = "long";       (* Type of "intptr_t" *)
+    uintptr_t = "unsigned long";      (* Type of "uintptr_t" *)
+    int_fast8_t = "signed char";
+    int_fast16_t = "long";
+    int_fast32_t = "long";
+    int_fast64_t = "long";
+    uint_fast8_t = "unsigned char";
+    uint_fast16_t = "unsigned long";
+    uint_fast32_t = "unsigned long";
+    uint_fast64_t = "unsigned long";
+    wint_t = "int";
+    sig_atomic_t = "int";
+    time_t = "long";
+    alignof_short = 2;
+    alignof_int = 4;
+    alignof_long = 8;
+    alignof_longlong = 8;
+    alignof_ptr = 8;
+    alignof_float = 4;
+    alignof_double = 8;
+    alignof_longdouble = 16;
+    alignof_str = 1;
+    alignof_fun = -1;
+    char_is_unsigned = true;
+    little_endian = true;
+    alignof_aligned = 16;
+    has__builtin_va_list = true;
+    compiler = "none";
+    cpp_arch_flags = [];
+    version = "N/A";
+    weof = "(-1)";
+    wordsize = "64";
+    posix_version = "";
+    bufsiz = "255";
+    eof = "(-1)";
+    fopen_max = "255";
+    filename_max = "4095";
+    path_max = "256";
+    tty_name_max = "255";
+    host_name_max = "255";
+    l_tmpnam = "63";
+    tmp_max = "1024";
+    rand_max = "0xFFFFFFFE";
+    mb_cur_max = "16";
+    nsig = "";
+    errno = [
+      "edom", "33";
+      "eilseq", "84";
+      "erange", "34";
+    ];
+    machdep_name = "dummy";
+    custom_defs = "";
+  }
+
+module Machdep = Datatype.Make_with_collections(struct
+    include Datatype.Serializable_undefined
+    let reprs = [dummy_machdep]
+    let name = "Machdep"
+    type t = Cil_types.mach
+    let compare : t -> t -> int = Stdlib.compare
+    let equal : t -> t -> bool = (=)
+    let hash : t -> int = Hashtbl.hash
+    let copy = Datatype.identity
+  end)
+
+
 (* -------------------------------------------------------------------------- *)
 (* --- Internal                                                           --- *)
 (* -------------------------------------------------------------------------- *)
diff --git a/src/kernel_services/ast_queries/cil_datatype.mli b/src/kernel_services/ast_queries/cil_datatype.mli
index efdc0387d21f1e6ae9daa8bd46bc1ec8517ba195..e145312e6c62f29d44dfbd6df84070e4ab1afabc 100644
--- a/src/kernel_services/ast_queries/cil_datatype.mli
+++ b/src/kernel_services/ast_queries/cil_datatype.mli
@@ -102,8 +102,6 @@ module Location: sig
   val equal_start_semantic : location -> location -> bool
 end
 
-module Localisation: Datatype.S with type t = localisation
-
 module Syntactic_scope:
   Datatype.S_with_collections with type t = syntactic_scope
 
@@ -369,6 +367,13 @@ module PredicateStructEq: S_with_collections_pretty with type t = predicate
 module Lexpr: S with type t = Logic_ptree.lexpr
 (** Beware: no pretty-printer is available. *)
 
+(**************************************************************************)
+(** {3 Machdep}                                                           *)
+(**************************************************************************)
+
+module Machdep: S_with_collections with type t = mach
+(** since 27.0-Cobalt *)
+
 (**/**)
 (* ****************************************************************************)
 (** {2 Internal API} *)
diff --git a/src/kernel_services/ast_queries/file.ml b/src/kernel_services/ast_queries/file.ml
index b15088fa8d6fd1432063c008cc1e9690028bccf3..213a01aa72e0f96f949d035b2793bb2151a65b44 100644
--- a/src/kernel_services/ast_queries/file.ml
+++ b/src/kernel_services/ast_queries/file.ml
@@ -23,7 +23,6 @@
 open Cil_types
 open Cil
 open Visitor
-open Cil_datatype
 
 type cpp_opt_kind = Gnu | Not_gnu | Unknown
 
@@ -267,81 +266,34 @@ let print_machdep fmt (m : Cil_types.mach) =
       (if m.char_is_unsigned then "unsigned" else "signed");
     Format.fprintf fmt "   machine is %s endian@\n"
       (if m.little_endian then "little" else "big") ;
-    Format.fprintf fmt "   strings are %s chars@\n"
-      (if m.const_string_literals then "const" else "writable") ;
-    Format.fprintf fmt "   assembly names %s leading '_'@\n"
-      (if m.underscore_name then "have" else "have no") ;
     Format.fprintf fmt "   compiler %s builtin __va_list@\n"
       (if m.has__builtin_va_list then "has" else "has not") ;
   end
 
-module DatatypeMachdep = Datatype.Make_with_collections(struct
-    include Datatype.Serializable_undefined
-    let reprs = [Machdeps.x86_32]
-    let name = "File.Machdep"
-    type t = Cil_types.mach
-    let compare : t -> t -> int = Stdlib.compare
-    let equal : t -> t -> bool = (=)
-    let hash : t -> int = Hashtbl.hash
-    let copy = Datatype.identity
-  end)
-
-let default_machdeps =
-  [ "x86_16", Machdeps.x86_16;
-    "x86_32", Machdeps.x86_32;
-    "x86_64", Machdeps.x86_64;
-    "gcc_x86_16", Machdeps.gcc_x86_16;
-    "gcc_x86_32", Machdeps.gcc_x86_32;
-    "gcc_x86_64", Machdeps.gcc_x86_64;
-    "ppc_32", Machdeps.ppc_32;
-    "msvc_x86_64", Machdeps.msvc_x86_64;
-  ]
-
-let regexp_existing_machdep_macro = Str.regexp "-D[ ]*__FC_MACHDEP_"
-
-let existing_machdep_macro () =
-  let extra = String.concat " " (Kernel.CppExtraArgs.get ()) in
-  try
-    ignore (Str.search_forward regexp_existing_machdep_macro extra 0);
-    true
-  with Not_found -> false
-
-let machdep_macro = function
-  | "x86_16"                -> "__FC_MACHDEP_X86_16"
-  | "gcc_x86_16"            -> "__FC_MACHDEP_GCC_X86_16"
-  | "x86_32"                -> "__FC_MACHDEP_X86_32"
-  | "gcc_x86_32"            -> "__FC_MACHDEP_GCC_X86_32"
-  | "x86_64"                -> "__FC_MACHDEP_X86_64"
-  | "gcc_x86_64"            -> "__FC_MACHDEP_GCC_X86_64"
-  | "ppc_32"                -> "__FC_MACHDEP_PPC_32"
-  | "msvc_x86_64"           -> "__FC_MACHDEP_MSVC_X86_64"
-  | s ->
-    let res = "__FC_MACHDEP_" ^ (String.uppercase_ascii s) in
-    Kernel.warning ~once:true
-      "machdep %s has no registered macro. Using %s for pre-processing" s res;
-    res
-
-module Machdeps =
-  State_builder.Hashtbl(Datatype.String.Hashtbl)(DatatypeMachdep)
-    (struct
-      let name = " File.Machdeps"
-      let size = 5
-      let dependencies = []
-    end)
+let machdep_dir () = Kernel.Share.get_dir ~mode:`Must_exist "machdeps"
 
-let mem_machdep s = Machdeps.mem s || List.mem_assoc s default_machdeps
+let regexp_machdep = Str.regexp "^machdep_\\([^.]*\\).yaml$"
 
-let new_machdep s m =
-  try
-    let cm = Machdeps.find s in
-    if not (cm = m) then
-      Kernel.abort "trying to register incompatible machdeps under name `%s'" s
-  with Not_found ->
-    Machdeps.add s m
+let default_machdep_file machdep =
+  let filename = "machdep_" ^ machdep ^ ".yaml" in
+  Filepath.Normalized.concat (machdep_dir()) filename
+
+let is_default_machdep machdep =
+  Filepath.Normalized.is_file (default_machdep_file machdep)
+
+let mem_machdep s = is_default_machdep s || Sys.file_exists s
+
+let default_machdeps () =
+  Array.fold_right
+    (fun s acc ->
+       if Str.string_match regexp_machdep s 0 then
+         Str.matched_group 1 s :: acc
+       else acc)
+    (Sys.readdir (machdep_dir() :> string))
+    []
 
 let pretty_machdeps fmt =
-  Machdeps.iter (fun x _ -> Format.fprintf fmt "@ %s" x);
-  List.iter (fun (x, _) -> Format.fprintf fmt "@ %s" x) default_machdeps
+  List.iter (fun s -> Format.fprintf fmt "@ %s" s) (default_machdeps())
 
 let machdep_help () =
   let m = Kernel.Machdep.get () in
@@ -358,23 +310,116 @@ let () = Cmdline.run_after_exiting_stage machdep_help
 let set_machdep () =
   let m = Kernel.Machdep.get () in
   if not (mem_machdep m) then
-    Kernel.abort "@[unsupported machine %s.@ Try one of%t.@]" m pretty_machdeps
+    Kernel.abort "@[unsupported machine '%s'.@ Either use a predefined name among %t,@ or an YAML machdep file.@]" m pretty_machdeps
 
 let () = Cmdline.run_after_configuring_stage set_machdep
 
+let yaml_dict_to_list = function
+  | `O l ->
+    let make_one acc (k,v) =
+      Result.(
+        bind acc
+          (fun l ->
+             match Yaml.Util.to_string v with
+             | Ok s -> Ok((k,s) :: l)
+             | Error (`Msg s) ->
+               Error (`Msg ("Unexpected value for key " ^ k ^ ": " ^ s))))
+    in
+    List.fold_left make_one (Ok []) l
+  | _ -> Error (`Msg "Unexpected YAML value instead of dictionary of strings")
+
+type mach = Cil_types.mach = {
+  sizeof_short: int;
+  sizeof_int: int;
+  sizeof_long: int ;
+  sizeof_longlong: int;
+  sizeof_ptr: int;
+  sizeof_float: int;
+  sizeof_double: int;
+  sizeof_longdouble: int;
+  sizeof_void: int;
+  sizeof_fun: int;
+  size_t: string;
+  ssize_t: string;
+  wchar_t: string;
+  ptrdiff_t: string;
+  intptr_t: string;
+  uintptr_t: string;
+  int_fast8_t: string;
+  int_fast16_t: string;
+  int_fast32_t: string;
+  int_fast64_t: string;
+  uint_fast8_t: string;
+  uint_fast16_t: string;
+  uint_fast32_t: string;
+  uint_fast64_t: string;
+  wint_t: string;
+  sig_atomic_t: string;
+  time_t: string;
+  alignof_short: int;
+  alignof_int: int;
+  alignof_long: int;
+  alignof_longlong: int;
+  alignof_ptr: int;
+  alignof_float: int;
+  alignof_double: int;
+  alignof_longdouble: int;
+  alignof_str: int;
+  alignof_fun: int;
+  char_is_unsigned: bool;
+  little_endian: bool;
+  alignof_aligned: int;
+  has__builtin_va_list: bool;
+  compiler: string;
+  cpp_arch_flags: string list;
+  version: string;
+  weof: string;
+  wordsize: string;
+  posix_version: string;
+  bufsiz: string;
+  eof: string;
+  fopen_max: string;
+  filename_max: string;
+  host_name_max: string;
+  tty_name_max: string;
+  l_tmpnam: string;
+  path_max: string;
+  tmp_max: string;
+  rand_max: string;
+  mb_cur_max: string;
+  nsig: string;
+  errno: (string * string) list [@of_yaml yaml_dict_to_list];
+  machdep_name: string;
+  custom_defs: string;
+}
+[@@deriving yaml]
+
 (* Local to this module. Use Cil.theMachine.theMachine outside *)
 let get_machdep () =
   let m = Kernel.Machdep.get () in
-  try
-    Machdeps.find m
-  with Not_found ->
-  try
-    List.assoc m default_machdeps
-  with Not_found -> (* Should not happen given the checks above *)
-    Kernel.fatal "Machdep %s not registered" m
+  let file =
+    if is_default_machdep m then default_machdep_file m
+    else Filepath.Normalized.of_string ~existence:Must_exist m
+  in
+  let res =
+    Result.bind
+      (Yaml_unix.of_file (Fpath.v (file:>string)))
+      mach_of_yaml
+  in
+  match res with
+  | Ok machdep -> machdep
+  | Error (`Msg s) ->
+    Kernel.abort "Error during machdep parsing: %s" s
+
+let print_machdep_header () =
+  if Kernel.PrintMachdepHeader.get () then begin
+    Machdep.gen_all_defines Format.std_formatter (get_machdep());
+    raise Cmdline.Exit
+  end else Cmdline.nop
+
+let () = Cmdline.run_after_exiting_stage print_machdep_header
 
-let list_available_machdeps () =
-  Machdeps.fold (fun m _ acc -> m :: acc) (List.map fst default_machdeps)
+let list_available_machdeps = default_machdeps
 
 let pretty_machdep ?fmt ?machdep () =
   let machine = match machdep with None -> get_machdep () | Some m -> m in
@@ -463,33 +508,14 @@ let build_cpp_cmd = function
     (* Hypothesis: the preprocessor is POSIX compliant,
        hence understands -I and -D. *)
     let fc_include_args =
-      if Kernel.FramaCStdLib.get () then [(Fc_config.framac_libc:>string)]
-      else []
-    in
-    let fc_define_args =
-      if not (existing_machdep_macro ())
-      then [machdep_macro (Kernel.Machdep.get ())]
+      if Kernel.FramaCStdLib.get () then
+        begin
+          let machdep_dir = Machdep.generate_machdep_header (get_machdep()) in
+          [(machdep_dir:>string); (Fc_config.framac_libc:>string)]
+        end
       else []
     in
-    let fc_define_args = "__FRAMAC__" :: fc_define_args in
-    (* Hypothesis: the preprocessor does support the arch-related
-       options tested when 'configure' was run. *)
-    let required_cpp_arch_args = (get_machdep ()).cpp_arch_flags in
-    let supported_cpp_arch_args, unsupported_cpp_arch_args =
-      List.partition (fun arg ->
-          List.mem arg Fc_config.preprocessor_supported_arch_options)
-        required_cpp_arch_args
-    in
-    if is_gnu_like = Unknown && not (Kernel.CppCommand.is_set ())
-       && unsupported_cpp_arch_args <> [] then
-      Kernel.warning ~once:true
-        "your preprocessor is not known to handle option(s) `%s', \
-         considered necessary for machdep `%s'. To ensure compatibility \
-         between your preprocessor and the machdep, consider using \
-         -cpp-command with the appropriate flags. \
-         Your preprocessor is known to support these flags: %s"
-        (concat_strs unsupported_cpp_arch_args) (Kernel.Machdep.get ())
-        (concat_strs Fc_config.preprocessor_supported_arch_options);
+    let fc_define_args = ["__FRAMAC__"] in
     let nostdinc_arg =
       if Kernel.FramaCStdLib.get() then add_if_gnu "-nostdinc"
       else []
@@ -511,7 +537,7 @@ let build_cpp_cmd = function
     in
     let supp_args =
       string_of_supp_args
-        (gnu_implicit_args @ supported_cpp_arch_args @
+        (gnu_implicit_args @
          extra_for_this_file @ (Kernel.CppExtraArgs.get ()))
         fc_include_args fc_define_args
     in
@@ -524,7 +550,7 @@ let build_cpp_cmd = function
     Kernel.feedback ~dkey:Kernel.dkey_pp
       "preprocessing with \"%s\""
       cpp_command_with_chdir;
-    Some (cpp_command_with_chdir, ppf, supported_cpp_arch_args)
+    Some (cpp_command_with_chdir, ppf)
 
 let abort_with_detailed_pp_message f cpp_command =
   let possible_cause =
@@ -562,7 +588,7 @@ let parse_cabs cpp_command = function
       Datatype.Filepath.pretty f;
     Frontc.parse f ()
   | NeedCPP (f, cmdl, _extra_for_this_file, is_gnu_like) ->
-    let cpp_command, ppf, logic_pp_args = Option.get cpp_command in
+    let cpp_command, ppf = Option.get cpp_command in
     Kernel.feedback "Parsing %a (with preprocessing)"
       Datatype.Filepath.pretty f;
     if Sys.command cpp_command <> 0 then begin
@@ -582,12 +608,9 @@ let parse_cabs cpp_command = function
                   "trying to preprocess annotation with an unknown \
                    preprocessor."; true))
       then begin
-        let supp_args =
-          Format.asprintf "%s" (concat_strs ~pre:" " ~sep:" " logic_pp_args)
-        in
         let ppf' =
           try Logic_preprocess.file ".c"
-                (replace_in_cpp_cmd cmdl supp_args)
+                (replace_in_cpp_cmd cmdl "")
                 (ppf : Filepath.Normalized.t :> string)
           with Sys_error _ as e ->
             safe_remove_file ppf;
@@ -913,7 +936,7 @@ let cleanup file =
   let visitor = object(self)
     inherit Visitor.frama_c_inplace
 
-    val mutable keep_stmt = Stmt.Set.empty
+    val mutable keep_stmt = Cil_datatype.Stmt.Set.empty
 
     val mutable changed = false
 
@@ -927,9 +950,9 @@ let cleanup file =
 
     method! vstmt_aux st =
       self#remove_lexical_annotations st;
-      let loc = Stmt.loc st in
+      let loc = Cil_datatype.Stmt.loc st in
       if Annotations.has_code_annot st || st.labels <> [] || st.sattr <> [] then
-        keep_stmt <- Stmt.Set.add st keep_stmt;
+        keep_stmt <- Cil_datatype.Stmt.Set.add st keep_stmt;
       match st.skind with
       | Block b ->
         (* queue is flushed afterwards*)
@@ -945,8 +968,9 @@ let cleanup file =
         b.bstmts <-
           List.filter
             (fun x ->
-               not (Cil.is_skip x.skind) || Stmt.Set.mem x keep_stmt ||
-               ( changed <- true; false) (* don't try this at home, kids...*)
+               not (Cil.is_skip x.skind)
+               || Cil_datatype.Stmt.Set.mem x keep_stmt
+               || (changed <- true; false)
             )
             b.bstmts;
         (* Now that annotations are in the table, we do not need to
@@ -1262,7 +1286,7 @@ let find_logic_info_decl li =
          | GAnnot (ga,_) ->
            if
              List.exists
-               (fun li' -> Logic_info.equal li li')
+               (fun li' -> Cil_datatype.Logic_info.equal li li')
                (extract_logic_infos ga)
            then raise (F.Found g)
          | _ -> ())
@@ -1284,12 +1308,12 @@ class reorder_ast: Visitor.frama_c_visitor =
   in
   object(self)
     inherit Visitor.frama_c_inplace
-    val mutable known_enuminfo = Enuminfo.Set.empty
-    val mutable known_compinfo = Compinfo.Set.empty
-    val mutable known_typeinfo = Typeinfo.Set.empty
-    val mutable known_var = Varinfo.Set.empty
-    val mutable known_logic_info = Logic_info.Set.empty
-    val mutable local_logic_info = Logic_info.Set.empty
+    val mutable known_enuminfo = Cil_datatype.Enuminfo.Set.empty
+    val mutable known_compinfo = Cil_datatype.Compinfo.Set.empty
+    val mutable known_typeinfo = Cil_datatype.Typeinfo.Set.empty
+    val mutable known_var = Cil_datatype.Varinfo.Set.empty
+    val mutable known_logic_info = Cil_datatype.Logic_info.Set.empty
+    val mutable local_logic_info = Cil_datatype.Logic_info.Set.empty
 
     (* globals that have to be declared before current declaration. *)
     val mutable needed_decls = []
@@ -1306,19 +1330,19 @@ class reorder_ast: Visitor.frama_c_visitor =
     val logic_info_deps = Global_annotation_graph.create ()
 
     method private add_known_enuminfo ei =
-      known_enuminfo <- Enuminfo.Set.add ei known_enuminfo
+      known_enuminfo <- Cil_datatype.Enuminfo.Set.add ei known_enuminfo
 
     method private add_known_compinfo ci =
-      known_compinfo <- Compinfo.Set.add ci known_compinfo
+      known_compinfo <- Cil_datatype.Compinfo.Set.add ci known_compinfo
 
     method private add_known_type ty =
-      known_typeinfo <- Typeinfo.Set.add ty known_typeinfo
+      known_typeinfo <- Cil_datatype.Typeinfo.Set.add ty known_typeinfo
 
     method private add_known_var vi =
-      known_var <- Varinfo.Set.add vi known_var
+      known_var <- Cil_datatype.Varinfo.Set.add vi known_var
 
     method private add_known_logic_info li =
-      known_logic_info <- Logic_info.Set.add li known_logic_info
+      known_logic_info <- Cil_datatype.Logic_info.Set.add li known_logic_info
 
     method private add_needed_decl g =
       needed_decls <- g :: needed_decls
@@ -1396,8 +1420,8 @@ class reorder_ast: Visitor.frama_c_visitor =
                   (Daxiomatic
                      (unique_name_recursive_axiomatic (),
                       entries, attr,
-                      Location.unknown),
-                   Location.unknown))::res)
+                      Cil_datatype.Location.unknown),
+                   Cil_datatype.Location.unknown))::res)
             entries []
         end else begin
           Global_annotation_graph.fold
@@ -1422,7 +1446,7 @@ class reorder_ast: Visitor.frama_c_visitor =
 
        | TNamed (ty,_) ->
          let g = find_typeinfo ty in
-         if not (Typeinfo.Set.mem ty known_typeinfo) then begin
+         if not (Cil_datatype.Typeinfo.Set.mem ty known_typeinfo) then begin
            self#add_needed_decl g;
            Stack.push g typedefs;
            Stack.push true subvisit;
@@ -1440,19 +1464,19 @@ class reorder_ast: Visitor.frama_c_visitor =
                    ty.tname)
              typedefs
        | TComp(ci,_) ->
-         if not (Compinfo.Set.mem ci known_compinfo) then begin
-           self#add_needed_decl (GCompTagDecl (ci,Location.unknown));
+         if not (Cil_datatype.Compinfo.Set.mem ci known_compinfo) then begin
+           self#add_needed_decl(GCompTagDecl(ci,Cil_datatype.Location.unknown));
            self#add_known_compinfo ci
          end
        | TEnum(ei,_) ->
-         if not (Enuminfo.Set.mem ei known_enuminfo) then begin
-           self#add_needed_decl (GEnumTagDecl (ei, Location.unknown));
+         if not (Cil_datatype.Enuminfo.Set.mem ei known_enuminfo) then begin
+           self#add_needed_decl(GEnumTagDecl(ei,Cil_datatype.Location.unknown));
            self#add_known_enuminfo ei
          end);
       DoChildren
 
     method! vvrbl vi =
-      if vi.vglob && not (Varinfo.Set.mem vi known_var) then begin
+      if vi.vglob && not (Cil_datatype.Varinfo.Set.mem vi known_var) then begin
         if Cil.isFunctionType vi.vtype then
           self#add_needed_decl (GFunDecl (Cil.empty_funspec(),vi,vi.vdecl))
         else
@@ -1465,7 +1489,7 @@ class reorder_ast: Visitor.frama_c_visitor =
       if not (Logic_env.is_builtin_logic_function lv.l_var_info.lv_name) then
         begin
           let g = find_logic_info_decl lv in
-          if not (Logic_info.Set.mem lv known_logic_info) then begin
+          if not(Cil_datatype.Logic_info.Set.mem lv known_logic_info) then begin
             self#add_annot_depend g;
             Stack.push true subvisit;
             (* visit will also push g in needed_annot. *)
@@ -1477,13 +1501,13 @@ class reorder_ast: Visitor.frama_c_visitor =
         end
 
     method private add_local_logic_info li =
-      local_logic_info <- Logic_info.Set.add li local_logic_info
+      local_logic_info <- Cil_datatype.Logic_info.Set.add li local_logic_info
 
     method private remove_local_logic_info li =
-      local_logic_info <- Logic_info.Set.remove li local_logic_info
+      local_logic_info <- Cil_datatype.Logic_info.Set.remove li local_logic_info
 
     method private is_local_logic_info li =
-      Logic_info.Set.mem li local_logic_info
+      Cil_datatype.Logic_info.Set.mem li local_logic_info
 
     method! vlogic_var_use lv =
       let logic_infos = Annotations.logic_info_of_global lv.lv_name in
@@ -1541,48 +1565,53 @@ class reorder_ast: Visitor.frama_c_visitor =
 
 module Remove_spurious = struct
   type env =
-    { typeinfos: Typeinfo.Set.t;
-      compinfos: Compinfo.Set.t;
-      enuminfos: Enuminfo.Set.t;
-      varinfos: Varinfo.Set.t;
-      logic_infos: Logic_info.Set.t;
+    { typeinfos: Cil_datatype.Typeinfo.Set.t;
+      compinfos: Cil_datatype.Compinfo.Set.t;
+      enuminfos: Cil_datatype.Enuminfo.Set.t;
+      varinfos: Cil_datatype.Varinfo.Set.t;
+      logic_infos: Cil_datatype.Logic_info.Set.t;
       kept: global list;
     }
 
   let treat_one_global acc g =
     match g with
-    | GType (ty,_) when Typeinfo.Set.mem ty acc.typeinfos -> acc
+    | GType (ty,_) when Cil_datatype.Typeinfo.Set.mem ty acc.typeinfos -> acc
     | GType (ty,_) ->
       { acc with
-        typeinfos = Typeinfo.Set.add ty acc.typeinfos;
+        typeinfos = Cil_datatype.Typeinfo.Set.add ty acc.typeinfos;
         kept = g :: acc.kept }
     | GCompTag _ -> { acc with kept = g :: acc.kept }
-    | GCompTagDecl(ci,_) when Compinfo.Set.mem ci acc.compinfos -> acc
+    | GCompTagDecl(ci,_)
+      when Cil_datatype.Compinfo.Set.mem ci acc.compinfos -> acc
     | GCompTagDecl(ci,_) ->
       { acc with
-        compinfos = Compinfo.Set.add ci acc.compinfos;
+        compinfos = Cil_datatype.Compinfo.Set.add ci acc.compinfos;
         kept = g :: acc.kept }
     | GEnumTag _ -> { acc with kept = g :: acc.kept }
-    | GEnumTagDecl(ei,_) when Enuminfo.Set.mem ei acc.enuminfos -> acc
+    | GEnumTagDecl(ei,_)
+      when Cil_datatype.Enuminfo.Set.mem ei acc.enuminfos -> acc
     | GEnumTagDecl(ei,_) ->
       { acc with
-        enuminfos = Enuminfo.Set.add ei acc.enuminfos;
+        enuminfos = Cil_datatype.Enuminfo.Set.add ei acc.enuminfos;
         kept = g :: acc.kept }
     | GVarDecl(vi,_) | GFunDecl (_, vi, _)
-      when Varinfo.Set.mem vi acc.varinfos -> acc
+      when Cil_datatype.Varinfo.Set.mem vi acc.varinfos -> acc
     | GVarDecl(vi,_) ->
       { acc with
-        varinfos = Varinfo.Set.add vi acc.varinfos;
+        varinfos = Cil_datatype.Varinfo.Set.add vi acc.varinfos;
         kept = g :: acc.kept }
     | GVar _ | GFun _ | GFunDecl _ -> { acc with kept = g :: acc.kept }
     | GAsm _ | GPragma _ | GText _ -> { acc with kept = g :: acc.kept }
     | GAnnot (a,_) ->
       let lis = extract_logic_infos a in
-      if List.exists (fun x -> Logic_info.Set.mem x acc.logic_infos) lis
+      if List.exists
+          (fun x -> Cil_datatype.Logic_info.Set.mem x acc.logic_infos)
+          lis
       then acc
       else begin
         let known_li =
-          List.fold_left (Fun.flip Logic_info.Set.add) acc.logic_infos lis
+          List.fold_left
+            (Fun.flip Cil_datatype.Logic_info.Set.add) acc.logic_infos lis
         in
         { acc with
           kept = g::acc.kept;
@@ -1591,11 +1620,11 @@ module Remove_spurious = struct
       end
 
   let empty =
-    { typeinfos = Typeinfo.Set.empty;
-      compinfos = Compinfo.Set.empty;
-      enuminfos = Enuminfo.Set.empty;
-      varinfos = Varinfo.Set.empty;
-      logic_infos = Logic_info.Set.empty;
+    { typeinfos = Cil_datatype.Typeinfo.Set.empty;
+      compinfos = Cil_datatype.Compinfo.Set.empty;
+      enuminfos = Cil_datatype.Enuminfo.Set.empty;
+      varinfos = Cil_datatype.Varinfo.Set.empty;
+      logic_infos = Cil_datatype.Logic_info.Set.empty;
       kept = [];
     }
 
@@ -1677,7 +1706,7 @@ let compute_sources_table cpp_commands =
     add_source_if_new all_sources_tbl (get_filepath file);
     match cmd_opt with
     | None -> ()
-    | Some (cpp_cmd, _ppf, _sl) ->
+    | Some (cpp_cmd, _ppf) ->
       let tmp_file = create_temp_file "audit_produce_sources" ".txt" in
       let tmp_file = (tmp_file :> string) in
       let cmd_for_sources = cpp_cmd ^ " -H -MM >/dev/null 2>" ^ tmp_file in
@@ -1750,7 +1779,7 @@ let check_source_hashes expected actual_table =
   end
 
 let print_and_exit cpp_commands =
-  let print_cpp_cmd (cpp_cmd, _ppf, _) =
+  let print_cpp_cmd (cpp_cmd, _ppf) =
     Kernel.result "Preprocessing command:@.%s" cpp_cmd
   in
   List.iter (fun (_f, ocmd) -> Option.iter print_cpp_cmd ocmd) cpp_commands;
diff --git a/src/kernel_services/ast_queries/file.mli b/src/kernel_services/ast_queries/file.mli
index f6ac175cf92ef311404e4a4be5cdb185c576eb88..b0da114f710eb07aa892549ae92e31cd826a4a98 100644
--- a/src/kernel_services/ast_queries/file.mli
+++ b/src/kernel_services/ast_queries/file.mli
@@ -53,29 +53,11 @@ val new_file_type:
     @see <https://frama-c.com/download/frama-c-plugin-development-guide.pdf> Plug-in Development Guide
 *)
 
-val new_machdep: string -> Cil_types.mach -> unit
-(** [new_machdep name module] registers a new machdep name as recognized by
-    Frama-C through The usual uses is
-    [Cmdline.run_after_loading_stage
-      (fun () -> File.new_machdep "my_machdep" my_machdep_implem)]
-    @since Nitrogen-20111001
-    @raise Invalid_argument if the given name already exists
-    @see <https://frama-c.com/download/frama-c-plugin-development-guide.pdf> Plug-in Development Guide *)
-
-val machdep_macro: string -> string
-(** [machdep_macro machine] returns the name of a macro __FC_MACHDEP_XXX so
-    that the preprocessor can select std lib definition consistent with
-    the selected machdep. This function will emit a warning if [machine] is
-    not known by default by the kernel and return __FC_MACHDEP_MACHINE in that
-    case.
-    @since Magnesium-20151001 (exported in the API)
-*)
-
 val list_available_machdeps: unit -> string list
 (** [list_available_machdeps ()] gives the list of the names of available
-    machdeps, starting with the ones added with new_machdep and ending with
-    the list of default machdeps.
-    @since 22.0-Titanium *)
+    machdeps in Frama-C's share path
+    @since 22.0-Titanium
+*)
 
 type code_transformation_category
 (** type of registered code transformations
diff --git a/src/kernel_services/ast_queries/logic_parse_string.ml b/src/kernel_services/ast_queries/logic_parse_string.ml
index db62131f6e9554636d042c46fb1b5b86777468eb..a75626bd53c6f3927ca95be6d93e1c7e40faa12e 100644
--- a/src/kernel_services/ast_queries/logic_parse_string.ml
+++ b/src/kernel_services/ast_queries/logic_parse_string.ml
@@ -30,40 +30,32 @@ exception Unbound of string
 let find_var kf kinstr ?label var =
   let vi =
     try
-      let vi = Globals.Vars.find_from_astinfo var (VLocal kf) in
-      (match kinstr with
-       | Kglobal -> vi (* don't refine search: the Kglobal here
-                          does not indicate the function contract, but merely
-                          the fact that we do not have any information about
-                          the targeted program point. Hence, no scope check
-                          can be performed or we might reject many legitimate
-                          terms and predicates.
-                       *)
-       | Kstmt stmt ->
-         let scope =
-           match label with
-           | None | Some "Here" | Some "Post" | Some "Old" -> stmt
+      let scope =
+        match kinstr with
+        | Kglobal -> Whole_function kf
+        | Kstmt stmt ->
+          (match label with
+           | None | Some "Here" | Some "Post" | Some "Old" -> Block_scope stmt
            | Some "Pre" -> raise Not_found (* no local variable in scope. *)
            | Some "Init" -> raise Not_found (* no local variable in scope. *)
            | Some "LoopEntry" | Some "LoopCurrent" ->
              if not (Kernel_function.stmt_in_loop kf stmt) then
                Kernel.fatal
                  "Use of LoopEntry or LoopCurrent outside of a loop";
-             Kernel_function.find_enclosing_loop kf stmt
+             Block_scope (Kernel_function.find_enclosing_loop kf stmt)
            | Some l ->
-             (try let s = Kernel_function.find_label kf l in !s
+             (try let s = Kernel_function.find_label kf l in Block_scope !s
               with Not_found ->
                 Kernel.fatal
                   "Use of label %s that does not exist in function %a"
-                  l Kernel_function.pretty kf)
-         in
-         if Kernel_function.var_is_in_scope scope vi then vi
-         else raise Not_found)
+                  l Kernel_function.pretty kf))
+      in
+      Globals.Vars.find_from_astinfo var scope
     with Not_found ->
     try
-      Globals.Vars.find_from_astinfo var (VFormal kf)
+      Globals.Vars.find_from_astinfo var (Formal kf)
     with Not_found ->
-      Globals.Vars.find_from_astinfo var VGlobal
+      Globals.Vars.find_from_astinfo var Global
   in
   cvar_to_lvar vi
 
diff --git a/src/kernel_services/ast_queries/logic_typing.ml b/src/kernel_services/ast_queries/logic_typing.ml
index 2aab058b278f481654b30c244eb060a8266414e1..13ea19b232fa3826cfcc3e388b49a4c67132d3a5 100644
--- a/src/kernel_services/ast_queries/logic_typing.ml
+++ b/src/kernel_services/ast_queries/logic_typing.ml
@@ -318,6 +318,11 @@ module Lenv = struct
     (* to determine in which post-state we should go in case of nested
        \at(\at(...,Post),Pre)
     *)
+    keep_qualifiers: bool;
+    (* indicates whether we should keep qualifiers in term's type.
+       Almost always false, except as head nodes of specific
+       clauses such as assigns or volatile.
+    *)
   }
 
   let string_of_current_label env =
@@ -411,7 +416,8 @@ module Lenv = struct
       current_logic_label = None;
       is_post_state = None;
       enclosing_post_state=None;
-      is_funspec=false
+      is_funspec=false;
+      keep_qualifiers=false;
     }
 
   let funspec () =
@@ -462,6 +468,9 @@ let post_state_env kind typ =
   let env = enter_post_state env kind in
   env
 
+let keep_qualifiers env = { env with Lenv.keep_qualifiers = true }
+let drop_qualifiers env = { env with Lenv.keep_qualifiers = false }
+
 type type_namespace = Typedef | Struct | Union | Enum
 
 module Type_namespace =
@@ -632,6 +641,9 @@ sig
     (term_offset * Cil_types.logic_type)
   val mk_cast:
     ?explicit:bool -> Cil_types.term -> Cil_types.logic_type -> Cil_types.term
+  val conditional_conversion:
+    Cil_types.location -> Logic_ptree.relation option ->
+    Cil_types.term -> Cil_types.term -> Cil_types.logic_type
   val term : Lenv.t -> Logic_ptree.lexpr -> term
   val predicate : Lenv.t -> Logic_ptree.lexpr -> predicate
   val code_annot :
@@ -1786,23 +1798,15 @@ struct
       in
       mk_mem b TNoOffset
 
+  let string_of_rel = function
+    | Eq -> "eq"
+    | Neq -> "ne"
+    | Le -> "le"
+    | Lt -> "lt"
+    | Ge -> "ge"
+    | Gt -> "gt"
 
-
-  let conditional_conversion loc env rel t1 t2 =
-    let is_rel = Option.is_some rel in
-    (* a comparison is mainly a function of type 'a -> 'a -> Bool/Prop.
-       performs the needed unifications on both sides.*)
-    let var = fresh_type_var "cmp" in
-    let env,_,_ =
-      partial_unif ~overloaded:false loc t1 t1.term_type var env in
-    let env,ty2,_ =
-      partial_unif ~overloaded:false loc t2 t2.term_type var env in
-    (* in case first partial unification did not instantiate all variables
-       we do another pass on t1 with information from t2.
-    *)
-    let env,ty1,_ =
-      partial_unif ~overloaded:false loc t1 t1.term_type var env
-    in
+  let conditional_conversion loc rel t1 t2 =
     let rec aux lty1 lty2 =
       match (unroll_type lty1), (unroll_type lty2) with
       | Ctype ty1, Ctype ty2 ->
@@ -1820,25 +1824,30 @@ struct
           else if is_enum_cst t1 lty2 then lty2
           else if is_enum_cst t2 lty1 then lty1
           else Ctype (C.conditionalConversion ty1 ty2)
-        else if isArithmeticType ty1 && isArithmeticType ty2 then begin
-          if is_same_type lty1 lty2 then begin
-            if is_rel then begin
-              let rel = Option.get rel in
-              let kind =
-                match Cil.unrollType ty1 with
-                | TFloat (FFloat,_) -> "float"
-                | TFloat (FDouble,_) -> "double"
-                | TFloat (FLongDouble,_) -> "long double"
-                | _ -> Kernel.fatal "floating point type expected"
-              in
-              let source = fst loc in
-              Kernel.warning ~source ~wkey:Kernel.wkey_acsl_float_compare
-                "comparing two %s values as real values. You might \
-                 want to use \\%s_%s instead" kind rel kind;
-              Lreal
-            end else lty1
-          end else Lreal
-        end else if is_same_ptr_type ty1 ty2 || is_same_array_type ty1 ty2 then
+        else if isArithmeticType ty1 && isArithmeticType ty2 then
+          begin
+            if is_same_type lty1 lty2 then
+              begin
+                match rel with
+                | None -> lty1
+                | Some rel ->
+                  let kind =
+                    match Cil.unrollType ty1 with
+                    | TFloat (FFloat,_) -> "float"
+                    | TFloat (FDouble,_) -> "double"
+                    | TFloat (FLongDouble,_) -> "long double"
+                    | _ -> Kernel.fatal "floating point type expected"
+                  in
+                  let source = fst loc in
+                  Kernel.warning ~source
+                    ~wkey:Kernel.wkey_acsl_float_compare
+                    "comparing two %s values as real values. You might \
+                     want to use \\%s_%s instead" kind
+                    (string_of_rel rel) kind;
+                  Lreal
+              end else Lreal
+          end else
+        if is_same_ptr_type ty1 ty2 || is_same_array_type ty1 ty2 then
           Ctype (C.conditionalConversion ty1 ty2)
         else if
           (isPointerType ty1 || isArrayType ty1) &&
@@ -1860,25 +1869,47 @@ struct
         when is_integral_type t && name = Utf8_logic.boolean ->
         Ltype(C.find_logic_type Utf8_logic.boolean,[])
       | 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 -> lty1
+      | Ltype (s1,l1), Ltype (s2,l2)
+        when s1.lt_name = s2.lt_name && List.for_all2 is_same_type l1 l2 ->
+        lty1
       | Lvar s1, Lvar s2 when s1 = s2 -> lty1
       | Linteger, Linteger -> Linteger
       | (Lreal | Linteger) , (Lreal | Linteger) -> Lreal
-      | Ltype ({lt_name = "\\list"} as lt,[t1]),
-        Ltype({lt_name="\\list"},[t2]) ->
-        Ltype(lt,[aux t1 t2])
-      | Ltype ({lt_name = "set"} as lt,[t1]), Ltype({lt_name="set"},[t2]) ->
-        Ltype(lt,[aux t1 t2])
+      | Ltype ({lt_name = "\\list"} as lt,[ty1]),
+        Ltype({lt_name="\\list"},[ty2]) ->
+        Ltype(lt,[aux ty1 ty2])
+      | Ltype ({lt_name = "set"} as lt,[ty1]), Ltype({lt_name="set"},[ty2]) ->
+        Ltype(lt,[aux ty1 ty2])
       (* implicit conversion to set *)
-      | Ltype ({lt_name = "set"} as lt,[t1]), t2
-      | t1, Ltype({lt_name="set"} as lt,[t2]) -> Ltype(lt,[aux t1 t2])
+      | Ltype ({lt_name = "set"} as lt,[ty1]), ty2
+      | ty1, Ltype({lt_name="set"} as lt,[ty2]) ->
+        Ltype(lt,[aux ty1 ty2])
       | t1, t2 when is_same_type t1 t2 -> t1
       | _ ->
         C.error loc "types %a and %a are not convertible"
           Cil_printer.pp_logic_type lty1 Cil_printer.pp_logic_type lty2
     in
-    let rt = aux ty1 ty2 in
+    aux t1.term_type t2.term_type
+
+  let conditional_common_type loc env rel t1 t2 =
+    (* a comparison is mainly a function of type 'a -> 'a -> Bool/Prop.
+       performs the needed unifications on both sides.*)
+    let var = fresh_type_var "cmp" in
+    let env,_,_ =
+      partial_unif ~overloaded:false loc t1 t1.term_type var env in
+    let env,ty2,_ =
+      partial_unif ~overloaded:false loc t2 t2.term_type var env in
+    (* in case first partial unification did not instantiate all variables
+       we do another pass on t1 with information from t2.
+    *)
+    let env,ty1,_ =
+      partial_unif ~overloaded:false loc t1 t1.term_type var env
+    in
+    let rt =
+      conditional_conversion loc rel
+        { t1 with term_type = ty1 }
+        { t2 with term_type = ty2 }
+    in
     env,rt,ty1,ty2
 
   type conversion = NoConv | ArithConv | IntegralConv | PointerConv
@@ -2515,7 +2546,7 @@ struct
       | Some t -> Tapp(info, label_assoc, tl), t
   and term_node ctxt env loc pl =
     let term = ctxt.type_term ctxt in
-    let term_ptr pl =
+    let term_ptr env pl =
       let t = term env pl in
       check_logic_pointer ~check_non_void:false loc t;
       t
@@ -2527,13 +2558,16 @@ struct
     | PLinitField _ ->
       ctxt.error loc "unsupported aggregated field construct"
     | PLupdate (t, toff, PLupdateCont cont) ->
+      let env = drop_qualifiers env in
       let t = term env t in
       normalize_update_cont ctxt env loc t (cont, toff)
     | PLupdate (t, toff, PLupdateTerm v) ->
+      let env = drop_qualifiers env in
       let t = term env t in
       normalize_update_term ctxt env loc t v toff
 
     | PLsizeof typ ->
+      let env = drop_qualifiers env in
       (match Logic_const.unroll_ltdef (logic_type ctxt loc env typ)
        with
          Ctype t -> TSizeOf t,Linteger
@@ -2545,7 +2579,7 @@ struct
         { lexpr_node = PLconstant (StringConstant s | WStringConstant s) } ->
       TSizeOfStr s, Linteger
     | PLsizeofE lexpr ->
-      let t = term env lexpr in
+      let t = term (drop_qualifiers env) lexpr in
       (match Logic_const.unroll_ltdef t.term_type with
        | Ctype _ -> TSizeOfE t, Linteger
        | _ -> if ctxt.silent then raise Backtrack;
@@ -2568,6 +2602,11 @@ struct
       Ctype (TPtr(Cil.theMachine.wcharType,[]))
     | PLvar x ->
       let old_val info =
+        let typ =
+          if env.Lenv.keep_qualifiers then info.lv_type
+          else
+            Logic_utils.logic_type_remove_qualifiers info.lv_type
+        in
         let term =  TLval (TVar info, TNoOffset) in
         if env.Lenv.is_funspec then begin
           let term =
@@ -2579,8 +2618,8 @@ struct
                  Tat(Logic_const.term ~loc term info.lv_type,
                      find_logic_label loc env "Old")
                | Some _ | None -> term)
-          in term, info.lv_type
-        end else term, info.lv_type
+          in term, typ
+        end else term, typ
       in
       begin
         try
@@ -2684,6 +2723,7 @@ struct
                   %s as constant" x)
       end
     | PLapp (f, labels, tl) ->
+      let env = drop_qualifiers env in
       let f = try (match (ctxt.find_macro f).lexpr_node with
           | PLvar (x) -> x
           | _ -> ctxt.error loc "invalid definition for macro %s" f)
@@ -2692,10 +2732,10 @@ struct
       fresh_type#reset ();
       lfun_app ctxt env loc f labels ttl
     | PLunop (Ubw_not, t) ->
-      let t = type_int_term ctxt env t in
+      let t = type_int_term ctxt (drop_qualifiers env) t in
       TUnOp (BNot, t), logic_arithmetic_promotion t.term_type
     | PLunop (Uminus, t) ->
-      let t = type_num_term ctxt env t in
+      let t = type_num_term ctxt (drop_qualifiers env) t in
       let ty = logic_arithmetic_promotion t.term_type in
       TUnOp (Neg, mk_cast t ty), ty
     | PLunop (Ustar, t) ->
@@ -2706,7 +2746,11 @@ struct
         let t = mk_logic_pointer_or_StartOf t in
         check_non_void_ptr loc t.term_type;
         let t = mk_mem t TNoOffset in
-        t.term_node, t.term_type
+        let typ =
+          if env.Lenv.keep_qualifiers then t.term_type
+          else Logic_utils.logic_type_remove_qualifiers t.term_type
+        in
+        t.term_node, typ
       end else begin
         ctxt.error loc "invalid type %a for `unary *'"
           Cil_printer.pp_logic_type t.term_type
@@ -2722,6 +2766,7 @@ struct
       t.term_node, t.term_type
     | PLbinop (t1, (Badd | Bsub | Bmul | Bdiv | Bmod
                    | Bbw_and | Bbw_or | Bbw_xor | Blshift | Brshift as op), t2) ->
+      let env = drop_qualifiers env in
       let t1 = term env t1 in
       let ty1 = t1.term_type in
       let t2 = term env t2 in
@@ -2788,6 +2833,10 @@ struct
     | PLdot (t, f) ->
       let t = term env t in
       let f_ofs, f_type = type_of_field loc f t.term_type in
+      let f_type =
+        if env.Lenv.keep_qualifiers then f_type
+        else Logic_utils.logic_type_remove_qualifiers f_type
+      in
       let t = lift_set (mk_dot env loc f_ofs f_type) t in
       t.term_node, t.term_type
 
@@ -2800,11 +2849,15 @@ struct
       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
+      let f_type =
+        if env.Lenv.keep_qualifiers then f_type
+        else Logic_utils.logic_type_remove_qualifiers f_type
+      in
       (mk_mem ~loc t f_ofs).term_node, f_type
 
     | PLarrget (t1, t2) ->
       let t1 = term env t1 in
-      let t2 = term env t2 in
+      let t2 = term (drop_qualifiers env) t2 in
       (* access to a C value (either array or pointer) *)
       let t'1, t'2, tres =
         if isLogicPointer t1 && is_integral_type t2.term_type then
@@ -2813,8 +2866,12 @@ struct
             (* memory access need a current label to have some semantics *)
             let t1 = mk_logic_pointer_or_StartOf t1 in
             check_non_void_ptr t1.term_loc t1.term_type;
-            (t1, t2,
-             set_conversion (type_of_pointed t1.term_type) t2.term_type)
+            let typ = type_of_pointed t1.term_type in
+            let typ =
+              if env.Lenv.keep_qualifiers then typ
+              else Logic_utils.logic_type_remove_qualifiers typ
+            in
+            (t1, t2, set_conversion typ t2.term_type)
           end
         else if is_integral_type t1.term_type && isLogicPointer t2
         then begin
@@ -2822,8 +2879,12 @@ struct
           (* memory access need a current label to have some semantics *)
           let t2 = mk_logic_pointer_or_StartOf t2 in
           check_non_void_ptr t2.term_loc t2.term_type;
-          (t2, t1,
-           set_conversion (type_of_pointed t2.term_type) t1.term_type)
+          let typ = type_of_pointed t2.term_type in
+          let typ =
+            if env.Lenv.keep_qualifiers then typ
+            else Logic_utils.logic_type_remove_qualifiers typ
+          in
+          (t2, t1, set_conversion typ t1.term_type)
         end
         else if (* purely logical array access. *)
           isLogicArrayType t1.term_type && is_integral_type t2.term_type
@@ -2843,11 +2904,11 @@ struct
       t.term_node, t.term_type
 
     | PLif (t1, t2, t3) ->
-      let t1 = type_bool_term ctxt env t1 in
+      let t1 = type_bool_term ctxt (drop_qualifiers env) t1 in
       let t2 = term env t2 in
       let t3 = term env t3 in
       let env,ty,ty2,ty3 =
-        conditional_conversion loc env None t2 t3 in
+        conditional_common_type loc env None t2 t3 in
       let t2 = { t2 with term_type = instantiate env t2.term_type } in
       let _,t2 =
         implicit_conversion
@@ -2873,7 +2934,7 @@ struct
     | PLbase_addr (l, t) ->
       (* base_addr need a current label to have some semantics *)
       let l = find_current_logic_label loc env l in
-      let t = term_ptr t in
+      let t = term_ptr (drop_qualifiers env) t in
       let t =
         lift_set
           (fun t -> Logic_const.term (Tbase_addr (l,t))
@@ -2882,14 +2943,14 @@ struct
     | PLoffset (l, t) ->
       (* offset need a current label to have some semantics *)
       let l = find_current_logic_label loc env l in
-      let t = term_ptr t in
+      let t = term_ptr (drop_qualifiers env) t in
       let t =
         lift_set (fun t -> Logic_const.term (Toffset (l,t)) Linteger) t
       in t.term_node, t.term_type
     | PLblock_length (l, t) ->
       (* block_length need a current label to have some semantics *)
       let l = find_current_logic_label loc env l in
-      let t = term_ptr t in
+      let t = term_ptr (drop_qualifiers env) t in
       let t =
         lift_set
           (fun t -> Logic_const.term (Tblock_length (l,t)) Linteger)
@@ -2897,6 +2958,7 @@ struct
       in t.term_node, t.term_type
     | PLresult ->
       (try let t = Lenv.find_var "\\result" env in
+         (* by construction, return type is a C type without qualifiers. *)
          match t.lv_type with
            Ctype ty ->
            TLval(TResult ty,TNoOffset), t.lv_type
@@ -2911,8 +2973,13 @@ struct
       (* no casts of tsets in grammar *)
       let ct = Logic_const.unroll_ltdef (logic_type ctxt loc env ty) in
       let { term_node; term_type } = mk_cast ~explicit:true t ct in
-      (term_node, term_type)
+      let typ =
+        if env.Lenv.keep_qualifiers then term_type
+        else Logic_utils.logic_type_remove_qualifiers term_type
+      in
+      (term_node, typ)
     | PLrel (t1, (Eq | Neq | Lt | Le | Gt | Ge as op), t2) ->
+      let env = drop_qualifiers env in
       let f _ op t1 t2 =
         (TBinOp(binop_of_rel op, t1, t2),
          Ltype(ctxt.find_logic_type Utf8_logic.boolean,[]))
@@ -2925,21 +2992,26 @@ struct
       let cfalse = ctxt.find_logic_ctor "\\false" in
       TDataCons(cfalse,[]), Ltype(cfalse.ctor_type,[])
     | PLlambda(prms,e) ->
+      let env = drop_qualifiers env in
       let (prms, env) = add_quantifiers ctxt loc ~kind:LVFormal prms env in
       let e = term env e in
       Tlambda(prms,e),Larrow(List.map (fun x -> x.lv_type) prms,e.term_type)
     | PLnot t ->
+      let env = drop_qualifiers env in
       let t = type_bool_term ctxt env t in
       TUnOp(LNot,t), Ltype (ctxt.find_logic_type Utf8_logic.boolean,[])
     | PLand (t1,t2) ->
+      let env = drop_qualifiers env in
       let t1 = type_bool_term ctxt env t1 in
       let t2 = type_bool_term ctxt env t2 in
       TBinOp(LAnd,t1,t2), Ltype (ctxt.find_logic_type Utf8_logic.boolean,[])
     | PLor (t1,t2) ->
+      let env = drop_qualifiers env in
       let t1 = type_bool_term ctxt env t1 in
       let t2 = type_bool_term ctxt env t2 in
       TBinOp(LOr,t1,t2), Ltype (ctxt.find_logic_type Utf8_logic.boolean,[])
     | PLtypeof t1 ->
+      let env = drop_qualifiers env in
       let t1 = term env t1 in
       Ttypeof t1, Ltype (ctxt.find_logic_type "typetag",[])
     | PLtype ty ->
@@ -2949,7 +3021,7 @@ struct
           ctxt.error loc "cannot take type tag of logic type"
       end
     | PLlet (ident, def, body) ->
-      let tdef = term env def in
+      let tdef = term (drop_qualifiers env) def in
       (* At least for now, the type is supposed to be fully instantiated.
          No generalization is needed. *)
       let var = Cil_const.make_logic_info_local ident in
@@ -2965,7 +3037,11 @@ struct
       var.l_body <- LBterm tdef;
       let env = Lenv.add_logic_info ident var env in
       let tbody = term env body in
-      Tlet(var,tbody), tbody.term_type
+      let typ =
+        if env.Lenv.keep_qualifiers then tbody.term_type
+        else Logic_utils.logic_type_remove_qualifiers tbody.term_type
+      in
+      Tlet(var,tbody), typ
     | PLcomprehension(t,quants,pred) ->
       let quants, env = add_quantifiers ctxt loc ~kind:LVQuant quants env in
       let t = term env t in
@@ -2973,7 +3049,11 @@ struct
         ctxt.error loc "sets of sets are not supported yet"
       end else begin
         let pred = Option.map (predicate env) pred in
-        Tcomprehension(t,quants,pred), (make_set_type t.term_type)
+        let typ =
+          if env.Lenv.keep_qualifiers then t.term_type
+          else Logic_utils.logic_type_remove_qualifiers t.term_type
+        in
+        Tcomprehension(t,quants,pred), (make_set_type typ)
       end
     | PLempty
     | PLset [] ->
@@ -2997,6 +3077,7 @@ struct
       Tinter locs, typ
     | PLlist l ->
       fresh_type#reset();
+      let env = drop_qualifiers env in
       let empty_list,typ_items =
         let empty_list,typ = lfun_app ctxt env loc "\\Nil" [] [] in
         empty_list,(type_of_list_elem typ)
@@ -3017,12 +3098,14 @@ struct
       in
       List.fold_left add_ahead (empty_list, (make_type_list_of typ_items)) l
     | PLrepeat (t1,t2) ->
+      let env = drop_qualifiers env in
       let t1 = term env t1 in
       let t2 = term env t2 in
       fresh_type#reset ();
       lfun_app ctxt env loc "\\repeat" [] [t1; t2]
     | PLrange (t1,t2) ->
       (* we allow range of floats/real.  *)
+      let env = drop_qualifiers env in
       let t1,ty1 = type_num_term_option ctxt env t1 in
       let t2,ty2 = type_num_term_option ctxt env t2 in
       (Trange(t1,t2),
@@ -3044,17 +3127,9 @@ struct
     let ty1 = t1.term_type in
     let t2 = ctxt.type_term ctxt env t2 in
     let ty2 = t2.term_type in
-    let rel = match op with
-      | Eq -> "eq"
-      | Neq -> "ne"
-      | Le -> "le"
-      | Lt -> "lt"
-      | Ge -> "ge"
-      | Gt -> "gt"
-    in
     let conditional_conversion t1 t2 =
       let env,t,ty1,ty2 =
-        conditional_conversion loc env (Some rel) t1 t2
+        conditional_common_type loc env (Some op) t1 t2
       in
       let t1 = { t1 with term_type = instantiate env t1.term_type } in
       let _,t1 =
@@ -3522,6 +3597,7 @@ struct
       (tl, Cil_types.From tf)
 
   let type_assign ctxt ~accept_formal env a =
+    let env = keep_qualifiers env in
     let module [@warning "-60"] C = struct end in
     match a with
       WritesAny -> Cil_types.WritesAny
@@ -4216,7 +4292,7 @@ struct
     | LDmodel_annot l ->
       Dmodel_annot (model_annot loc l,loc);
     | LDvolatile (tsets, (rd_opt, wr_opt)) ->
-      let env = Lenv.empty () in
+      let env = keep_qualifiers (Lenv.empty ()) in
       let ctxt = base_ctxt env in
       let tsets =
         let accept_formal = false in
diff --git a/src/kernel_services/ast_queries/logic_typing.mli b/src/kernel_services/ast_queries/logic_typing.mli
index 8d267131d5fa5283bf600d79cc72b211c74c5bf5..f9f671cb80244851652504b355a6e099fe1e218a 100644
--- a/src/kernel_services/ast_queries/logic_typing.mli
+++ b/src/kernel_services/ast_queries/logic_typing.mli
@@ -163,6 +163,23 @@ sig
   val mk_cast:
     ?explicit:bool -> Cil_types.term -> Cil_types.logic_type -> Cil_types.term
 
+  (** [conditional_conversion loc rel t1 t2]
+      tries to find a common type between two terms, either as part of
+      a comparison or a conditional.
+      comparisons can notably introduce logic coercions to Real, potentially
+      with a warning if [acsl-float-compare] is active.
+
+      @param loc the location of the comparison. Can be used in error/warning msg
+      @param rel the relation, or [None] for a conditional
+      @param t1 first term
+      @param t2 second term
+
+      @since 27.0-Cobalt
+  *)
+  val conditional_conversion:
+    Cil_types.location -> Logic_ptree.relation option ->
+    Cil_types.term -> Cil_types.term -> Cil_types.logic_type
+
   (** type-checks a term. *)
   val term : Lenv.t -> Logic_ptree.lexpr -> term
 
diff --git a/src/kernel_services/ast_queries/logic_utils.ml b/src/kernel_services/ast_queries/logic_utils.ml
index 0af75114af3d582931d53b4b77dd12730b333c34..d09f0711ca63a3def21b31357b56ec6503b4d8ea 100644
--- a/src/kernel_services/ast_queries/logic_utils.ml
+++ b/src/kernel_services/ast_queries/logic_utils.ml
@@ -108,7 +108,7 @@ let plain_array_to_ptr ty =
               Kernel.fatal
                 "Inconsistent information: I know the length of \
                  array type %a, but not of its elements."
-                Cil_printer.pp_typ tarr
+                !Cil.pp_typ_ref tarr
           in
           (* Normally, overflow is checked in bitsSizeOf itself *)
           let la = AInt (Integer.of_int len) in
@@ -123,6 +123,16 @@ let plain_array_to_ptr ty =
 
 let array_to_ptr = plain_or_set plain_array_to_ptr
 
+let logic_type_remove_qualifiers =
+  let plain typ =
+    match unroll_type typ with
+    | Ctype t ->
+      let t' = Cil.type_remove_qualifier_attributes t in
+      if Cil_datatype.Typ.equal t t' then typ else Ctype t'
+    | _ -> typ
+  in
+  Logic_const.transform_element plain
+
 let coerce_type typ =
   let ty = Cil.unrollType typ in
   if Cil.isIntegralType ty then Linteger
@@ -217,7 +227,7 @@ let mk_logic_pointer_or_StartOf t =
     if is_C_array t then mk_logic_StartOf t else t
   else
     Kernel.fatal ~source:(fst t.term_loc)
-      "%a is neither a pointer nor a C array" Cil_printer.pp_term t
+      "%a is neither a pointer nor a C array" !Cil.pp_term_ref t
 
 let equal_ltype = Cil_datatype.Logic_type.equal
 
@@ -398,7 +408,7 @@ let scalar_term_conversion conversion t =
   | Ctype (TVoid _ | TNamed _ | TComp _ | TBuiltin_va_list _)
     -> Kernel.fatal
          "Cannot convert a term of type %a"
-         Cil_printer.pp_logic_type t.term_type
+         !Cil.pp_logic_type_ref t.term_type
 
 let scalar_term_to_predicate =
   let conversion ~loc is_eq t1 t2 =
@@ -572,7 +582,7 @@ and expr_to_boolean e =
     else
       Kernel.fatal
         "Cannot convert into predicate the C expression %a"
-        Cil_printer.pp_exp e
+        !Cil.pp_exp_ref e
 
 and expr_to_predicate e =
   let open Cil_types in
@@ -618,7 +628,7 @@ and expr_to_predicate e =
     else
       Kernel.fatal
         "Cannot convert into predicate the C expression %a"
-        Cil_printer.pp_exp e
+        !Cil.pp_exp_ref e
 
 and expr_to_ipredicate e =
   Logic_const.new_predicate (expr_to_predicate e)
@@ -2066,7 +2076,7 @@ let merge_assigns_list l1 l2 =
           let loc = asgn1.it_content.term_loc in
           Kernel.warning ~once:true ~source:(fst loc)
             "location %a is not present in all assigns clauses"
-            Cil_printer.pp_identified_term asgn1;
+            !Cil.pp_identified_term_ref asgn1;
         end;
         (asgn1, from1) :: aux q1 l2
       | Some (asgn2, from2 as cl2), q2 ->
@@ -2081,8 +2091,8 @@ let merge_assigns_list l1 l2 =
           Kernel.warning ~once:true ~source:(fst loc1)
             "@[incompatible@ from@ clauses (%a:'%a'@ and@ %a:'%a').@ \
              Keeping@ only@ the first@ one.@]"
-            Cil_printer.pp_location loc1 Cil_printer.pp_from cl1
-            Cil_printer.pp_location loc2 Cil_printer.pp_from cl2;
+            !Cil.pp_location_ref loc1 !Cil.pp_from_ref cl1
+            !Cil.pp_location_ref loc2 !Cil.pp_from_ref cl2;
           cl1 :: aux q1 q2
         end
   in
@@ -2140,7 +2150,7 @@ let merge_behaviors ?(oldloc=Cil_datatype.Location.unknown) ~silent old_behavior
                 (fun fmt ->
                    if Kernel.debug_atleast 1 then
                      Format.fprintf fmt ":@ @[%a@] vs. @[%a@]"
-                       Cil_printer.pp_behavior b Cil_printer.pp_behavior old_b)
+                       !Cil.pp_behavior_ref b !Cil.pp_behavior_ref old_b)
             ;
             old_b.b_assumes <- merge_ip_list old_b.b_assumes b.b_assumes;
             old_b.b_requires <- merge_ip_list old_b.b_requires b.b_requires;
@@ -2362,7 +2372,7 @@ class complete_types =
 
 let complete_types f = Cil.visitCilFile (new complete_types) f
 
-let pointer_comparable ?loc t1 t2 =
+let pointer_comparable ?loc ?(label=Logic_const.here_label) t1 t2 =
   let preds = Logic_env.find_all_logic_functions "\\pointer_comparable" in
   let cfct_ptr = TPtr (TFun(Cil.voidType,None,false,[]),[]) in
   let fct_ptr = Ctype cfct_ptr in
@@ -2404,7 +2414,7 @@ let pointer_comparable ?loc t1 t2 =
     with Not_found ->
       Kernel.fatal "built-in predicate \\pointer_comparable not found"
   in
-  Logic_const.unamed ?loc (Papp (pi, [], [t1;t2]))
+  Logic_const.unamed ?loc (Papp (pi, [label], [t1;t2]))
 
 let is_min_max_function name li =
   li.l_var_info.lv_name = name &&
diff --git a/src/kernel_services/ast_queries/logic_utils.mli b/src/kernel_services/ast_queries/logic_utils.mli
index 1e94484c56da83f416155892b65fd691c73a0069..8ab9618a28e2b85de0278a8a57e59387440a5c95 100644
--- a/src/kernel_services/ast_queries/logic_utils.mli
+++ b/src/kernel_services/ast_queries/logic_utils.mli
@@ -78,6 +78,11 @@ val logicCType : logic_type -> typ
 (** transforms an array into pointer. *)
 val array_to_ptr : logic_type -> logic_type
 
+(** removes qualifiers if logic_type is a C type, identity otherwise.
+    @since 27.0-Cobalt
+*)
+val logic_type_remove_qualifiers: logic_type -> logic_type
+
 (** C type to logic type, with implicit conversion for arithmetic types.
     @since 21.0-Scandium
 *)
@@ -146,9 +151,12 @@ val numeric_coerce: logic_type -> term -> term
 (** \valid_range *)
 (* val mk_pvalid_range: ?loc:location -> term * term * term -> predicate *)
 
-val pointer_comparable: ?loc:location -> term -> term -> predicate
-(** \pointer_comparable
-    @since Fluorine-20130401 *)
+val pointer_comparable:
+  ?loc:location -> ?label:logic_label -> term -> term -> predicate
+(** \pointer_comparable. [label] defaults to {!Logic_const.here_label}
+    @since Fluorine-20130401
+    @before 27.0-Cobalt no [label] argument, as the builtin did not take a label
+*)
 
 (** {2 Conversion from exp to term} *)
 
diff --git a/src/kernel_services/plugin_entry_points/kernel.ml b/src/kernel_services/plugin_entry_points/kernel.ml
index 656d60a3774fceaca97f28f2d8ac9d387ad585c1..a3507a0ac08575dd11e660d284a235db59edd8c4 100644
--- a/src/kernel_services/plugin_entry_points/kernel.ml
+++ b/src/kernel_services/plugin_entry_points/kernel.ml
@@ -429,6 +429,18 @@ module PrintMachdep =
       let help = "pretty print selected machdep"
     end)
 
+let () = Parameter_customize.set_group help
+let () = Parameter_customize.set_cmdline_stage Cmdline.Exiting
+let () = Parameter_customize.set_negative_option_name ""
+module PrintMachdepHeader =
+  False
+    (struct
+      let module_name = "PrintMachdepHeader"
+      let option_name = "-print-machdep-header"
+      let help =
+        "print on standard output the content of the generated __fc_machdep.h"
+    end)
+
 let () = Parameter_customize.set_group help
 let () = Parameter_customize.set_negative_option_name ""
 module DumpDependencies =
diff --git a/src/kernel_services/plugin_entry_points/kernel.mli b/src/kernel_services/plugin_entry_points/kernel.mli
index 0c9a85462af183fe4fa69472d76847ca85d3c3cf..de72d6bb4dee30e023ad0cd0ce900a075ee3444f 100644
--- a/src/kernel_services/plugin_entry_points/kernel.mli
+++ b/src/kernel_services/plugin_entry_points/kernel.mli
@@ -320,6 +320,10 @@ module PrintMachdep : Parameter_sig.Bool
 (** Behavior of option "-print-machdep"
     @since Phosphorus-20170501-beta1 *)
 
+module PrintMachdepHeader : Parameter_sig.Bool
+(** Behavior of option "-print-machdep-header"
+    @since 27.0-Cobalt *)
+
 module PrintLibc: Parameter_sig.Bool
 (** Behavior of option "-print-libc"
     @since Phosphorus-20170501-beta1 *)
diff --git a/src/libraries/project/state_builder.ml b/src/libraries/project/state_builder.ml
index cb369ad1045dee8526dbab6490b672807fed3683..c93f9c167b30cdc49e3c100f6542147c4a548e67 100644
--- a/src/libraries/project/state_builder.ml
+++ b/src/libraries/project/state_builder.ml
@@ -490,9 +490,11 @@ module type Hashtbl = sig
     ?cmp:(key -> key -> int) -> (key -> data -> 'a -> 'a) -> 'a -> 'a
   val memo: ?change:(data -> data) -> (key -> data) -> key -> data
   val find: key -> data
+  val find_opt: key -> data option
   val find_all: key -> data list
   val mem: key -> bool
   val remove: key -> unit
+  val to_seq: unit -> (key * data) Seq.t
 end
 
 module Hashtbl
@@ -548,6 +550,7 @@ struct
   let replace key v = H.replace !state key v
   let add key v = H.add !state key v
   let find key = H.find !state key
+  let find_opt key = H.find_opt !state key
   let find_all key = H.find_all !state key
   let mem key = H.mem !state key
   let remove key = H.remove !state key
@@ -555,6 +558,7 @@ struct
   let iter_sorted ?cmp f = H.iter_sorted ?cmp f !state
   let fold f acc = H.fold f !state acc
   let fold_sorted ?cmp f acc = H.fold_sorted ?cmp f !state acc
+  let to_seq () = H.to_seq !state
 
   let memo ?change f key =
     try
diff --git a/src/libraries/project/state_builder.mli b/src/libraries/project/state_builder.mli
index 22ca6683820b4526024778cd2c3fef2a661fdc28..60a7bacace307b8face4ba02c71688789fa19cb1 100644
--- a/src/libraries/project/state_builder.mli
+++ b/src/libraries/project/state_builder.mli
@@ -351,11 +351,20 @@ module type Hashtbl = sig
   (** Return the current binding of the given key.
       @raise Not_found if the key is not in the table. *)
 
+  val find_opt: key -> data option
+  (** Return the current binding of the given key, or None if no such binding
+      exists.
+      @since 27.0-Cobalt *)
+
   val find_all: key -> data list
   (** Return the list of all data associated with the given key. *)
 
   val mem: key -> bool
   val remove: key -> unit
+
+  val to_seq: unit -> (key * data) Seq.t
+  (** Iterate on the whole table.
+      @since 27.0-Cobalt *)
 end
 
 (** @see <https://frama-c.com/download/frama-c-plugin-development-guide.pdf> Plug-in Development Guide
diff --git a/src/libraries/utils/json.mll b/src/libraries/utils/json.mll
index 47dfb1329c2d0ef5d9a2e23b2ebbe10846a64b0c..2017df4f36951a3090fbfacc045dd31a8fe485ab 100644
--- a/src/libraries/utils/json.mll
+++ b/src/libraries/utils/json.mll
@@ -334,7 +334,6 @@ let rec merge_assoc_lists la lb =
   List.rev r
 
 let merge_object path json_root_obj =
-  let open Yojson.Basic.Util in
   let existing_root_obj =
     try
       match Hashtbl.find json_tbl path with
@@ -343,14 +342,13 @@ let merge_object path json_root_obj =
     with Not_found ->
       `Assoc []
   in
-  let existing_assoc = existing_root_obj |> to_assoc in
-  let new_assoc = json_root_obj |> to_assoc in
+  let existing_assoc = existing_root_obj |> Yojson.Basic.Util.to_assoc in
+  let new_assoc = json_root_obj |> Yojson.Basic.Util.to_assoc in
   let merged = merge_assoc_lists existing_assoc new_assoc in
   let merged_obj = `Assoc merged in
   Hashtbl.replace json_tbl path merged_obj
 
 let merge_array path json_root_array =
-  let open Yojson.Basic.Util in
   let existing_root_array =
     try
       match Hashtbl.find json_tbl path with
@@ -359,8 +357,8 @@ let merge_array path json_root_array =
     with Not_found ->
       `List []
   in
-  let existing_list = existing_root_array |> to_list in
-  let new_list = json_root_array |> to_list in
+  let existing_list = existing_root_array |> Yojson.Basic.Util.to_list in
+  let new_list = json_root_array |> Yojson.Basic.Util.to_list in
   let merged_list = `List (existing_list @ new_list) in
   Hashtbl.replace json_tbl path merged_list
 
diff --git a/src/libraries/utils/task.ml b/src/libraries/utils/task.ml
index ff296b6638cad3631833af244f0b0ed0407da11f..557953250f45cd4473a3b7229cc64e2764cef2e3 100644
--- a/src/libraries/utils/task.ml
+++ b/src/libraries/utils/task.ml
@@ -36,7 +36,7 @@ let error = function
 (* ------------------------------------------------------------------------ *)
 
 type 'a status =
-  | Timeout of int
+  | Timeout of float
   | Canceled
   | Result of 'a
   | Failed of exn
@@ -206,7 +206,7 @@ let sync m t = lock m >>= t >>? fun _ -> unlock m
 type cmd = {
   name : string ;
   timed : bool ;
-  timeout : int ;
+  timeout : float ;
   time_start : float ;
   time_stop : float ;
   mutable time_killed : bool ;
@@ -227,9 +227,9 @@ let start_command ~timeout ?time ?stdout ?stderr cmd args =
          Format.pp_print_string fmt cmd ;
          Array.iter
            (fun c -> Format.fprintf fmt "@ %s" c) args) ;
-    let timed = timeout > 0 || time <> None in
+    let timed = timeout > 0.0 || time <> None in
     let time_start = if timed then Unix.gettimeofday () else 0.0 in
-    let time_stop = if timeout > 0 then time_start +. float_of_int timeout else 0.0 in
+    let time_stop = if timeout > 0.0 then time_start +. timeout else 0.0 in
     let async = Command.command_async ?stdout ?stderr cmd args in
     {
       name = cmd ;
@@ -251,7 +251,7 @@ let ping_command cmd coin =
       if coin = Kill then (kill () ; Wait 100)
       else
         let time_now = if cmd.timed then Unix.gettimeofday () else 0.0 in
-        if cmd.timeout > 0 && time_now > cmd.time_stop then
+        if cmd.timeout > 0.0 && time_now > cmd.time_stop then
           begin
             set_time cmd (time_now -. cmd.time_start) ;
             Kernel.debug ~dkey:Kernel.dkey_task "timeout '%s'" cmd.name ;
@@ -282,7 +282,7 @@ let ping_command cmd coin =
       "failure '%s' [%s]" cmd.name (Printexc.to_string e) ;
     Return (Failed e)
 
-let command ?(timeout=0) ?time ?stdout ?stderr cmd args = todo
+let command ?(timeout=0.0) ?time ?stdout ?stderr cmd args = todo
     begin fun () ->
       let cmd = start_command ~timeout ?time ?stdout ?stderr cmd args in
       Monad.async (ping_command cmd)
diff --git a/src/libraries/utils/task.mli b/src/libraries/utils/task.mli
index 0471763487a2b4d8ee4ca22c2615709d10fea0dc..bcb501bb306fab57d64721e5bdfbd08610312bcb 100644
--- a/src/libraries/utils/task.mli
+++ b/src/libraries/utils/task.mli
@@ -29,7 +29,7 @@
 
 type 'a task
 type 'a status =
-  | Timeout of int
+  | Timeout of float
   | Canceled
   | Result of 'a
   | Failed of exn
@@ -134,7 +134,7 @@ val sync : mutex -> (unit -> 'a task) -> 'a task
 (* ************************************************************************* *)
 
 val command :
-  ?timeout:int ->
+  ?timeout:float ->
   ?time:float ref ->
   ?stdout:Buffer.t ->
   ?stderr:Buffer.t ->
diff --git a/src/plugins/alias/.gitignore b/src/plugins/alias/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..bf8b4fea7803f726f79270ec0f26987cc09914f7
--- /dev/null
+++ b/src/plugins/alias/.gitignore
@@ -0,0 +1,3 @@
+/_build
+tests/**/result
+tests/*/oracle/dune
diff --git a/src/plugins/alias/API.ml b/src/plugins/alias/API.ml
new file mode 100644
index 0000000000000000000000000000000000000000..84509b9cd278681df533efcc7fe046c4ee086a6f
--- /dev/null
+++ b/src/plugins/alias/API.ml
@@ -0,0 +1,153 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2023                                               *)
+(*    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
+
+(** Points-to graphs datastructure. *)
+module G = Abstract_state.G
+
+module LSet = Abstract_state.LSet
+
+module Abstract_state = Abstract_state
+
+let check_computed () =
+  if not (Analysis.is_computed ())
+  then
+    Options.abort "Static analysis must be called before any function of the API can be called"
+
+
+let lset
+    (get_set : Abstract_state.t -> LSet.t)
+    (kf : kernel_function) (s : stmt) =
+  check_computed ();
+  match Analysis.get_state_before_stmt kf s with
+  | None -> LSet.empty
+  | Some state -> get_set state
+
+let points_to_set kf s lv = lset (Abstract_state.points_to_set lv) kf s
+
+let new_points_to_set_stmt kf s lv =
+  let get_set state =
+    let new_state = Analysis.do_stmt state s in
+    Abstract_state.points_to_set lv new_state
+  in
+  lset get_set kf s
+
+let aliases_stmt kf s lv =
+  lset (Abstract_state.find_all_aliases lv) kf s
+
+let new_aliases_stmt kf s lv =
+  let get_set state =
+    let new_state = Analysis.do_stmt state s in
+    Abstract_state.find_all_aliases lv new_state
+  in
+  lset get_set kf s
+
+let points_to_set_kf (kf : kernel_function) (lv : lval) =
+  check_computed ();
+  if Kernel_function.has_definition kf
+  then
+    let s = Kernel_function.find_return kf in
+    new_points_to_set_stmt kf s lv
+  else
+    Options.abort "points_to_set_kf: function %a has no definition" Kernel_function.pretty kf
+
+let aliases_kf (kf : kernel_function) (lv : lval) =
+  check_computed ();
+  if Kernel_function.has_definition kf
+  then
+    let s = Kernel_function.find_return kf in
+    new_aliases_stmt kf s lv
+  else
+    Options.abort "aliases_kf: function %a has no definition" Kernel_function.pretty kf
+
+let fundec_stmts (kf : kernel_function) (lv : lval) =
+  check_computed ();
+  if Kernel_function.has_definition kf
+  then
+    List.map
+      (fun s -> s, new_aliases_stmt kf s lv)
+      (Kernel_function.get_definition kf).sallstmts
+  else
+    Options.abort "fundec_stmts: function %a has no definition" Kernel_function.pretty kf
+
+
+let fold_points_to_set f_fold acc kf s lv =
+  LSet.fold (fun e a -> f_fold a e) (points_to_set kf s lv) acc
+
+let fold_aliases_stmt f_fold acc kf s lv =
+  LSet.fold (fun e a -> f_fold a e) (aliases_stmt kf s lv) acc
+
+let fold_new_aliases_stmt f_fold acc kf s lv =
+  LSet.fold (fun e a -> f_fold a e) (new_aliases_stmt kf s lv) acc
+
+let fold_points_to_set_kf (f_fold: 'a -> lval -> 'a) (acc: 'a) (kf:kernel_function) (lv:lval) : 'a =
+  LSet.fold (fun e a -> f_fold a e) (points_to_set_kf kf lv) acc
+
+let fold_aliases_kf (f_fold : 'a -> lval -> 'a) (acc : 'a) (kf : kernel_function) (lv : lval) : 'a =
+  LSet.fold (fun e a -> f_fold a e) (aliases_kf kf lv) acc
+
+let fold_fundec_stmts (f_fold: 'a -> stmt -> lval -> 'a) (acc: 'a) (kf:kernel_function) (lv:lval) : 'a =
+  List.fold_left
+    (fun acc (s, set) ->
+       LSet.fold (fun lv a -> f_fold a s lv) set acc
+    )
+    acc
+    (fundec_stmts kf lv)
+
+let are_aliased (kf: kernel_function) (s:stmt) (lv1: lval) (lv2:lval) : bool =
+  check_computed ();
+  match Analysis.get_state_before_stmt kf s with
+    None -> false
+  | Some state ->
+    let setv1 = Abstract_state.find_all_aliases lv1 state in
+    LSet.mem lv2 setv1
+
+let fold_vertex (f_fold : 'a -> G.V.t -> lval -> 'a) (acc: 'a) (kf: kernel_function) (s:stmt) (lv: lval) : 'a =
+  check_computed ();
+  match Analysis.get_state_before_stmt kf s with
+    None -> acc
+  | Some state ->
+    let v : G.V.t = Abstract_state.find_vertex lv state in
+    let set_aliases = Abstract_state.find_aliases lv state in
+    LSet.fold (fun lv a-> f_fold a v lv) set_aliases acc
+
+let fold_vertex_closure  (f_fold : 'a -> G.V.t -> lval -> 'a) (acc: 'a) (kf: kernel_function)  (s:stmt) (lv: lval) : 'a =
+  check_computed ();
+  match Analysis.get_state_before_stmt kf s with
+    None -> acc
+  | Some state ->
+    let list_closure : (G.V.t * LSet.t) list = Abstract_state.find_transitive_closure lv state in
+    List.fold_left
+      (fun acc (i,s) -> LSet.fold (fun lv a -> f_fold a i lv) s acc)
+      acc
+      list_closure
+
+let get_state_before_stmt =
+  Analysis.get_state_before_stmt
+
+let call_function a f res args =
+  match Analysis.get_summary f with
+    None -> None
+  | Some su -> Some(Abstract_state.call a res args su)
+
+let simplify_lval = Simplified.Lval.simplify
diff --git a/src/plugins/alias/API.mli b/src/plugins/alias/API.mli
new file mode 100644
index 0000000000000000000000000000000000000000..2ea9b4efc629d7612596bf442c96376370ba6b4b
--- /dev/null
+++ b/src/plugins/alias/API.mli
@@ -0,0 +1,121 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2023                                               *)
+(*    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).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** External API of the plugin Alias *)
+
+open Cil_types
+
+(** Points-to graphs datastructure. *)
+module G: Graph.Sig.G
+
+(** Set of [lval]s. Differs from Cil_datatype.Lval.Set in that is uses a
+    different comparison function ([Cil_datatype.LvalStructEq.compare]). *)
+module LSet : sig
+  include Set.S with type elt = lval
+
+  val pretty: Format.formatter -> t -> unit
+end
+
+(** NB : do the analysis BEFORE using any of those functions *)
+
+
+(** points-to set of lval [lv] at the end of function [kf]. *)
+val points_to_set_kf : kernel_function -> lval -> LSet.t
+
+(** aliases of lval [lv] at the end of function [kf]. *)
+val aliases_kf : kernel_function -> lval -> LSet.t
+
+(** list of pairs [s, e] where [e] is the set of lval aliased to [v] after
+    statement [s] in function [kf]. *)
+val fundec_stmts : kernel_function -> lval -> (stmt * LSet.t) list
+
+
+(** [fold_points_to_set f acc kf s lv] folds [f acc] over all the lvals in the
+    points-to set of the given lval [lv] right before stmt [s] in function
+    [kf]. *)
+val fold_points_to_set:
+  ('a -> lval -> 'a) -> 'a -> kernel_function -> stmt -> lval -> 'a
+
+(** [fold_aliases_stmt f acc kf s lv] folds [f acc] over all the aliases of the
+    given lval [lv] right before stmt [s] in function [kf]. *)
+val fold_aliases_stmt:
+  ('a -> lval -> 'a) -> 'a -> kernel_function -> stmt -> lval -> 'a
+
+(** [fold_new_aliases_stmt f acc kf s lv] folds [f acc] over all the aliases of
+    the given lval [lv] created by stmt [s] in function [kf]. *)
+val fold_new_aliases_stmt:
+  ('a -> lval -> 'a) -> 'a -> kernel_function -> stmt -> lval -> 'a
+
+(** [fold_points_to_set_kf f acc kf lv] folds [f acc] over the points-to set of lval
+    [lv] at the end of function [kf]. *)
+val fold_points_to_set_kf :
+  ('a -> lval -> 'a) -> 'a -> kernel_function -> lval -> 'a
+
+(** [fold_aliases_kf f acc kf lv] folds [f acc] over all the aliases of lval
+    [lv] at the end of function [kf]. *)
+val fold_aliases_kf:
+  ('a -> lval -> 'a) -> 'a -> kernel_function -> lval -> 'a
+
+(** [fold_fundec_stmts f acc kf v] folds [f acc s e] on the list of
+    pairs [s, e] where [e] is the set of lval aliased to [v] after statement [s]
+    in function [kf]. *)
+val fold_fundec_stmts:
+  ('a -> stmt -> lval -> 'a) -> 'a -> kernel_function -> lval -> 'a
+
+(** [are_aliased kf s lv1 lv2] returns true if and only if the two
+    lvals [lv1] and [lv2] are aliased before stmt [s] in function
+    [kf]. *)
+val are_aliased: kernel_function -> stmt -> lval -> lval -> bool
+
+(** [fold_vertex f acc kf s v] folds [f acc i lv] to all [lv] in [i], where [i] is
+    the vertex that represents the equivalence class of [v] before statement [s] in function [kf]. *)
+val fold_vertex:
+  ('a -> G.V.t -> lval -> 'a) -> 'a  -> kernel_function -> stmt -> lval  -> 'a
+
+(** [fold_vertex_closure f acc kf s v] is the transitive closure of function
+    [fold_vertex]. *)
+val fold_vertex_closure:
+  ('a -> G.V.t -> lval -> 'a) -> 'a  -> kernel_function -> stmt -> lval  -> 'a
+
+
+(** direct access to the abstract state. See Abstract_state.mli *)
+
+module Abstract_state : Abstract_state.S
+
+(** [get_state_before_stmt f s] gets the abstract state computed after
+    statement [s] in function [f]. Returns [None] if
+    the abstract state is bottom or not computed. *)
+val get_state_before_stmt :  kernel_function -> stmt -> Abstract_state.t option
+
+
+(** [call_function a f Some(res) args] computes the abstract state
+    after the instruction res=f(args) where res is a lval. [a] is the
+    abstract state before the call. If function [f] returns no value,
+    use [call_function a f None args] instead. Returns [None] if
+    the abstract state [a] is bottom or not computed. *)
+val call_function: Abstract_state.t -> kernel_function -> lval option -> exp list -> Abstract_state.t option
+
+
+(** [simplify_lval lv] returns a lval where every index of an array is
+    replaced by 0, evey pointer arithmetic is simplified to an access
+    to an array *)
+val simplify_lval: lval -> lval
diff --git a/src/plugins/gui/GSourceView.2.mli b/src/plugins/alias/Alias.ml
similarity index 85%
rename from src/plugins/gui/GSourceView.2.mli
rename to src/plugins/alias/Alias.ml
index a6a222088e5e324fe7fb3ea54e35e35ca34cb921..fe144bb2b96ff10ef8b8f29240892e52c4dd1390 100644
--- a/src/plugins/gui/GSourceView.2.mli
+++ b/src/plugins/alias/Alias.ml
@@ -20,15 +20,17 @@
 (*                                                                        *)
 (**************************************************************************)
 
-(* compatibility between gtksourceview 2 and 3. *)
-include module type of GSourceView2
 
-val make_marker_attributes:
-  source:source_view ->
-  category:string ->
-  priority: int ->
-  ?background: Gdk.color ->
-  ?pixbuf:GdkPixbuf.pixbuf ->
-  ?icon_name:string ->
-  unit ->
-  unit
+module Analysis = Analysis
+
+module API = API
+
+let main () =
+  if Options.Enabled.get() then
+    begin
+      Analysis.compute ();
+      Options.debug "Analysis complete";
+    end
+
+let () =
+  Db.Main.extend main
diff --git a/src/plugins/gui/debug_manager.mli b/src/plugins/alias/Alias.mli
similarity index 89%
rename from src/plugins/gui/debug_manager.mli
rename to src/plugins/alias/Alias.mli
index 1d0f25a886ea6cee40f8a686c691359cfcb397e1..32413b01810b62d778604e2c0b9c6188b7498db3 100644
--- a/src/plugins/gui/debug_manager.mli
+++ b/src/plugins/alias/Alias.mli
@@ -20,10 +20,13 @@
 (*                                                                        *)
 (**************************************************************************)
 
-(** Nothing exported. Automatic registration. *)
+(** Interface for the Alias plug-in. *)
 
-(*
-Local Variables:
-compile-command: "make -C ../../.."
-End:
-*)
+module Analysis: sig
+  (** see file analysis.mli for documentation *)
+  val compute : unit -> unit
+  val clear : unit -> unit
+end
+
+
+module API = API
diff --git a/src/plugins/alias/README.md b/src/plugins/alias/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..7dc75b04fa8aa09845800030779fa2cbd8486d57
--- /dev/null
+++ b/src/plugins/alias/README.md
@@ -0,0 +1,78 @@
+# May-Alias Analysis plugin
+
+Alias is a Frama-C plugin that implements:
+- a points-to analysis, i.e. an over-approximation of the possible values a
+  pointer may point to at run-time.
+- a may-alias analysis, i.e. an over-approximation of the possible aliases
+  between pointer variables (and, more generally, memory regions) of the
+  program.
+
+Two pointers are called aliases of each other if they point at runtime to the
+same memory location. In that case changing the value of one pointer also
+changes the value of the other pointer and vice versa.
+
+The plugin implements a variant of « Steensgaard's algorithm ».
+
+## Usage
+
+To run the may-alias analysis either:
+- call the function `Alias.Analysis.compute`
+- run `frama-c` with the `-alias` flag
+
+Please run `frama-c -alias-h` for more information on command-line flags.
+
+## API
+
+`Alias.Analysis` provides functions to run the analysis and clear the analysis
+results.
+The module `Alias.API` provides function to access the analysis results.
+
+## Limitations
+
+This plugin implements a path-insensitive analysis based on purely syntactic
+reasoning, with out numerical domains/values computations. When some branch
+condition appears in the program, any alias in any branch is considered.
+Therefore the analysis is efficient, whereas the results are not very precise.
+
+### Unsupported constructs
+- recursive functions
+- user-defined variadic functions
+- function declared and used without being defined (i.e., no function body)
+- function pointers
+- assembly code
+- instructions longjmp and setjmp
+- complex instruction goto that breaks the natural control-flow of the program
+- heterogeneous casts (e.g., casts from integers to pointers or conversely)
+- union type
+- dynamic memory allocation, except if done once at the beginning of the
+  program, whichever the execution path is.
+
+### Imprecisely-supported constructs
+- non-complex instruction goto
+- homogeneous casts
+- recursive datatype, e.g., multiple levels of pointer dereferencing
+- pointer arithmetic, and array and structure accesses
+- variable-length arrays
+- volatile attributes
+
+## Building and Installation
+
+The plug-in is included by default when installing Frama-C.
+
+To build the and install the plugin with profiling install the package
+landmarks-ppx and run:
+1. `dune build --instrument-with landmarks`
+2. `dune install --instrument-with landmarks`
+The plugin will then echo profiling information to stderr.
+
+Note that this plugin uses assertions extensively, which has considerable
+performance cost. Building and installing using the `--release` flag disables
+these assertions.
+
+## Project Members
+
+Allan Blanchard
+Loïc Correnson
+Tristan Le Gall
+Jan Rochel
+Julien Signoles
diff --git a/src/plugins/alias/abstract_state.ml b/src/plugins/alias/abstract_state.ml
new file mode 100644
index 0000000000000000000000000000000000000000..b1cc43122d90c913a6dcd876a1b4c21f71f1feb6
--- /dev/null
+++ b/src/plugins/alias/abstract_state.ml
@@ -0,0 +1,971 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2023                                               *)
+(*    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 Graph
+
+open Cil_types
+
+open Cil_datatype
+
+open Simplified
+
+module VSet = Datatype.Int.Set
+module VMap = Datatype.Int.Map
+
+module Lval = Simplified.Lval
+
+module LSet = struct
+  include Set.Make (Lval)
+
+  let pretty fmt s =
+    Format.fprintf fmt "{@[";
+    let is_first = ref true in
+    iter (fun e ->
+        if !is_first
+        then is_first := false
+        else Format.fprintf fmt ",@ ";
+        Format.fprintf fmt "%a" Lval.pretty e
+      )
+      s;
+    Format.fprintf fmt "@]}"
+end
+
+module LMap = struct
+  include Map.Make (Lval)
+
+  let pretty f fmt m =
+    let is_first = ref true in
+    Format.fprintf fmt "{@[<hov 2>";
+    iter (fun k v ->
+        if not !is_first
+        then Format.fprintf fmt ",@,"
+        else is_first := false;
+        Format.fprintf fmt " %a -> %a" Lval.pretty k f v
+      )
+      m;
+    Format.fprintf fmt " @]}"
+end
+
+module G = Persistent.Digraph.ConcreteBidirectional(Datatype.Int)
+
+module V = G.V
+
+(* like LMap, but organized with offset and specialized functions *)
+module LLMap =
+struct
+  module OMap = Offset.Map
+  (* each t is a map (lhost,NoOffset) -> offset -> V.t *)
+  type t = (V.t OMap.t) LMap.t
+
+  let empty : t = LMap.empty
+
+  let mem (lv : lval) (m:t) =
+    let lv, off = Cil.removeOffsetLval lv in
+    try
+      OMap.mem off (LMap.find lv m)
+    with
+      Not_found -> false
+
+  let find (lv : lval) (m:t) : V.t =
+    let lv, off = Cil.removeOffsetLval lv in
+    OMap.find off (LMap.find lv m)
+
+  let add (lv : lval) (v:V.t) (m:t) :t  =
+    let lv, off = Cil.removeOffsetLval lv in
+    let mo = try LMap.find lv m with Not_found -> OMap.empty in
+    LMap.add lv (OMap.add off v mo) m
+
+  let iter f = LMap.iter @@ fun lv -> OMap.iter @@ fun o -> f @@ Cil.addOffsetLval o lv
+
+  let map f = LMap.map @@ OMap.map f
+
+  let pretty fmt =
+    let is_first = ref true in
+    LMap.iter (fun lv ->
+        OMap.iter
+          (fun o v -> let lv =  Cil.addOffsetLval o lv in
+            if !is_first then is_first := false else Format.fprintf fmt "@;<3>";
+            Format.fprintf fmt "@ @[%a:%d@]" Lval.pretty lv v))
+
+  (* left-biased *)
+  let union = LMap.union @@ fun _ l r -> Some (OMap.union (fun _ l _r -> Some l) l r)
+
+  let intersect =
+    let intersect_omap l r = match l, r with
+      | Some l, Some r -> Some (l,r)
+      | _ -> None
+    in
+    let intersect_lmap l r = match l, r with
+      | Some l, Some r ->
+        let omap = OMap.merge (fun _ -> intersect_omap) l r in
+        if OMap.is_empty omap then None else Some omap
+      | _ -> None
+    in
+    LMap.merge @@ fun _ -> intersect_lmap
+
+  let to_seq m = LMap.fold (fun lv omap -> OMap.fold (fun o v s -> Seq.cons (lv,o,v) s) omap) m Seq.empty
+
+  (* specialized functions *)
+  let rec is_sub_offset o1 o2 =
+    match (o1,o2) with
+      NoOffset, _ -> true
+    | Index (e1,o1), Index (e2,o2) when Cil_datatype.ExpStructEq.equal e1 e2 -> is_sub_offset o1 o2
+    | Field (f1,o1), Field (f2,o2) when Fieldinfo.equal f1 f2 ->  is_sub_offset o1 o2
+    | _ -> false
+
+  (* finds all the lval lv1 apearing in [m] such as there exists an offset o1 and lv1 + o1 = lv *)
+  let find_upper_offsets (lv : lval) (m:t) : V.t LMap.t =
+    let lv, off = Cil.removeOffsetLval lv in
+    let mo = try LMap.find lv m with Not_found -> OMap.empty in
+    let f_filter o _v = is_sub_offset o off in
+    let mo = OMap.filter f_filter mo in
+    OMap.fold
+      (fun o -> let lv = Cil.addOffsetLval o lv in LMap.add lv)
+      mo
+      LMap.empty
+
+end
+
+module type S =
+sig
+  (* see abstract_state.mli for coments *)
+  type t
+  val get_graph: t -> G.t
+  val get_lval_set : G.V.t -> t -> LSet.t
+  val pretty : ?debug:bool -> Format.formatter -> t -> unit
+  val print_dot : string -> t -> unit
+  val find_vertex : lval -> t -> G.V.t
+  val find_aliases : lval -> t -> LSet.t
+  val find_all_aliases : lval -> t -> LSet.t
+  val points_to_set : lval -> t -> LSet.t
+  val find_transitive_closure : lval -> t -> (G.V.t * LSet.t) list
+  val is_included : t -> t -> bool
+end
+
+type t = {
+  graph : G.t;
+  lmap : LLMap.t ; (* lmap(lv) is a table [offset->v] where the vertex v corresponding to lval (lv+offset), in other words (lv+offset) is in label(v) *)
+  vmap : LSet.t VMap.t ;(* reverse of lmap *)
+}
+
+let node_counter = ref 0
+let fresh_node_id () =
+  let id = !node_counter in
+  node_counter := !node_counter + 1;
+  id
+
+(* find functions *)
+let find_lset (v:V.t) (x:t) : LSet.t =
+  try VMap.find v x.vmap
+  with Not_found -> LSet.empty
+
+let find_aliases (lv:lval) (x:t) =
+  let lv = Lval.simplify lv in
+  try
+    let v = LLMap.find lv x.lmap in
+    find_lset v x
+  with Not_found -> LSet.empty
+
+let rec get_points_to (v:V.t) (x:t) : LSet.t =
+  assert (G.mem_vertex x.graph v);
+  let set_predecessors =
+    List.fold_left
+      (fun acc v -> LSet.union acc (get_points_to v x))
+      LSet.empty
+      (G.pred x.graph v)
+  in
+  LSet.union
+    (find_lset v x)
+    (LSet.map Lval.points_to set_predecessors)
+
+let aliases_of_vertex (v:V.t) (x:t) : LSet.t =
+  assert (G.mem_vertex x.graph v);
+  let list_pred = G.pred x.graph v in
+  List.fold_left
+    (fun acc v -> LSet.union acc (get_points_to v x))
+    LSet.empty
+    list_pred
+
+let succ_of_lval (lv:lval) (x:t) : int option =
+  let lv = Lval.simplify lv in
+  try begin
+    let v = LLMap.find lv x.lmap in
+    match G.succ x.graph v with
+    | [] -> None
+    | [succ_v] -> Some succ_v
+    | _ -> Options.fatal "invariant violated (more than 1 successor)"
+  end with Not_found -> None
+
+let find_all_aliases (lv:lval) (x:t) : LSet.t =
+  match succ_of_lval lv x with
+  | None -> LSet.empty
+  | Some succ_v -> aliases_of_vertex succ_v x
+
+let points_to_set (lv:lval) (x:t) : LSet.t =
+  match succ_of_lval lv x with
+  | None -> LSet.empty
+  | Some succ_v -> find_lset succ_v x
+
+let get_graph (x:t) = x.graph
+
+(* renamed for the interface *)
+let get_lval_set = find_lset
+
+
+(* printing functions *)
+
+let print_debug fmt (x:t) =
+  Format.fprintf fmt "@[<v>";
+  Format.fprintf fmt "@[Edges:";
+  G.iter_edges (fun v1 v2 -> Format.fprintf fmt "@;<3 2>@[%d → %d@]" v1 v2) x.graph;
+  Format.fprintf fmt "@]@;<6>";
+  Format.fprintf fmt "@[LMap:@;<3 2>";
+  LLMap.pretty fmt x.lmap;
+  Format.fprintf fmt "@]@;<6>";
+  Format.fprintf fmt "@[VMap:@;<2>";
+  VMap.iter (fun v ls -> Format.fprintf fmt "@;<2 2>@[%d:%a@]" v LSet.pretty ls) x.vmap;
+  Format.fprintf fmt "@]";
+  Format.fprintf fmt "@]"
+
+let print_graph fmt (x:t) =
+  let is_first = ref true in
+  let print_edge v1 v2 =
+    if !is_first then is_first := false else Format.fprintf fmt "@;<3>";
+    let print_node v fmt lset = Format.fprintf fmt "%d:%a" v LSet.pretty lset in
+    Format.fprintf fmt "@[%a@] → @[%a@]"
+      (print_node v1) (VMap.find v1 x.vmap)
+      (print_node v2) (VMap.find v2 x.vmap)
+  in
+  if G.nb_edges x.graph = 0
+  then Format.fprintf fmt "<empty>"
+  else G.iter_edges print_edge x.graph
+
+let print_aliases fmt (x:t) =
+  let is_first = ref true in
+  let print_alias_set _ set_lv =
+    if !is_first then is_first := false else Format.fprintf fmt "@;<2>";
+    LSet.pretty fmt set_lv
+  in
+  let alias_set_of_vertex i _ =
+    let aliases = aliases_of_vertex i x in
+    if LSet.cardinal aliases >= 2 then Some aliases else None
+  in
+  let alias_sets = VMap.filter_map alias_set_of_vertex x.vmap in
+  if VMap.is_empty alias_sets
+  then Format.fprintf fmt "<none>"
+  else VMap.iter print_alias_set alias_sets
+
+(** invariants of type t must be true before and after each functon call *)
+let assert_invariants (x:t) : unit =
+  (* check that all vertex of the graph have entries in vmap,
+     and are integer between 0 and node_counter, and have at most 1 successor *)
+  assert (!node_counter >= 0);
+  let assert_vertex (v:V.t) =
+    assert (v >= 0);
+    assert (v < !node_counter);
+    assert (VMap.mem v x.vmap);
+    assert (List.length (G.succ x.graph v) <= 1)
+  in
+  G.iter_vertex assert_vertex x.graph;
+  let assert_edge v1 v2 =
+    assert (v1 <> v2);
+    assert (G.mem_vertex x.graph v1);
+    assert (G.mem_vertex x.graph v2)
+  in
+  G.iter_edges assert_edge x.graph;
+  let assert_lmap (lv : lval) (v:V.t) =
+    assert (G.mem_vertex x.graph v);
+    assert (LSet.mem lv (VMap.find v x.vmap))
+  in
+  LLMap.iter assert_lmap x.lmap;
+  let assert_vmap (v:V.t) (ls:LSet.t) =
+    assert (G.mem_vertex x.graph v);
+    (* TODO: we removed the invariant because of OSCS*)
+    (* if not (LSet.is_empty ls)
+     * then
+     *   begin
+     *     let lv = LSet.choose ls in
+     *     let is_ptr_lv = Lval.is_pointer lv in
+     *     assert (LSet.for_all (fun x -> Lval.is_pointer x = is_ptr_lv) ls)
+     *   end; *)
+    assert (LSet.fold (fun lv acc -> acc && V.equal (LLMap.find lv x.lmap) v) ls true)
+  in
+  VMap.iter assert_vmap x.vmap
+
+(* Ensure that assert_invariants is not executed if the -noassert flag is supplied. *)
+let assert_invariants x = assert (assert_invariants x; true)
+
+let pretty ?(debug = false) fmt (x:t) =
+  if debug then
+    try
+      assert_invariants x;
+      print_graph fmt x
+    with Assert_failure _ -> print_debug fmt x
+  else
+    print_aliases fmt x
+
+(** .dot printing functions*)
+let find_vertex_name_ref = Extlib.mk_fun "find_vertex_name"
+
+module Dot = Graphviz.Dot (struct
+    include G
+    let edge_attributes _ = []
+    let default_edge_attributes _ = []
+    let get_subgraph _ = None
+    let vertex_attributes _ = [`Shape `Box]
+    let vertex_name (v:V.t) =
+      let lset = !find_vertex_name_ref v in
+      let fmt = Format.str_formatter in
+      Format.fprintf fmt "\"%a\"" LSet.pretty lset;
+      Format.flush_str_formatter ()
+    let default_vertex_attributes _ = []
+    let graph_attributes _ = []
+  end)
+
+let print_dot filename (a:t) =
+  let file = open_out filename in
+  find_vertex_name_ref :=
+    (fun v -> find_lset v a
+    );
+  Dot.output_graph file a.graph;
+  close_out file
+
+(* find functions, part 2 *)
+let rec closure_find_lset (v:V.t) (x:t) : (V.t * LSet.t) list =
+  match G.succ x.graph v with
+    [] -> [v, find_lset v x]
+  | [v_next] -> (v, find_lset v x)::(closure_find_lset v_next x)
+  | _ -> Options.fatal ("this shall not happen (invariant broken)")
+
+let find_transitive_closure  (lv:lval) (x:t) : (G.V.t * LSet.t) list =
+  let lv = Lval.simplify lv in
+  assert_invariants x;
+  try closure_find_lset (LLMap.find lv x.lmap) x with Not_found -> []
+(* TODO : what about offsets ? *)
+
+(* NOTE on "constant vertex": a constant vertex represents an unamed
+   scalar value (type bottom in steensgaard's paper), or the address
+   of a variable. It means that in [vmap], its associated LSet is
+   empty.  By definition, constant vertex cannot be associated to a
+   lval in [lmap] *)
+let create_cst_vertex (x:t) : V.t * t =
+  let new_v = fresh_node_id () in
+  new_v,
+  {
+    graph = G.add_vertex x.graph new_v;
+    lmap = x.lmap ;
+    vmap = VMap.add new_v LSet.empty x.vmap
+  }
+
+(* find all the aliases of lv1 in x, for create_vertex *)
+let find_all_aliases_of_offset (lv1 : lval) (x: t) : LSet.t =
+  let lvals_to_be_searched = decompose_lval lv1 in
+  (* for each lval, find the set of aliases *)
+  let f_map (lv,o) =
+    try VMap.find (LLMap.find lv x.lmap) x.vmap, o
+    with Not_found -> LSet.empty, o
+  in
+  Options.debug ~level:9 "decompose_lval %a : [@[<hov 2>" Lval.pretty lv1;
+  List.iter (fun (x, o) -> Options.debug ~level:9 " (%a,%a) " Lval.pretty x Offset.pretty o) lvals_to_be_searched;
+  Options.debug ~level:9 "@]]";
+  let aliases = List.map f_map lvals_to_be_searched in
+  (*  for each lval of the Lset, add the offset and add it to the resulting set *)
+  let f_fold_left (acc : LSet.t) (ls,o) =
+    LSet.fold (fun lv -> LSet.add @@ Cil.addOffsetLval o lv) ls acc
+  in
+  List.fold_left f_fold_left (LSet.singleton lv1) aliases
+
+(* returns the new vertex and the new graph *)
+(* only for function find_or_create vertex *)
+let create_vertex_simple (lv:lval) (x:t) : V.t * t =
+  let new_v = fresh_node_id () in
+  let new_g = G.add_vertex x.graph new_v in
+  (* find all the alias of lv (because of offset) *)
+  let set_of_aliases : LSet.t = find_all_aliases_of_offset lv x in
+  (* add all these aliases *)
+  Options.debug ~level:9 "all_aliases of %a : %a " Lval.pretty lv LSet.pretty set_of_aliases;
+  let new_lmap =
+    LSet.fold
+      (fun lv acc -> assert (not (LLMap.mem lv x.lmap)); LLMap.add lv new_v acc)
+      set_of_aliases
+      x.lmap
+  in
+  let new_vmap = VMap.add new_v set_of_aliases x.vmap in
+
+  let new_x =
+    {
+      graph = new_g ;
+      lmap = new_lmap ;
+      vmap = new_vmap ;
+    }
+  in
+  assert_invariants new_x;
+  match lv with
+  | Var v, NoOffset ->
+    begin
+      match v.vtype with
+        TPtr _ ->
+        (* then add a constant vertex *)
+        let another_v, new_x = create_cst_vertex new_x in
+        let new_g = G.add_edge new_x.graph new_v another_v in
+        new_v, {new_x with graph = new_g}
+      | _ -> new_v, new_x
+    end
+  | _ -> new_v , new_x
+
+let diff_offset (lv1 : lval) (lv2 : lval) =
+  let rec f_diff_offset o1 o2 =
+    match o1, o2 with
+      NoOffset, _ -> o2
+    | Field (_,o1), Field (_,o2) -> f_diff_offset o1 o2
+    | Index (_,o1), Index (_,o2) -> f_diff_offset o1 o2
+    | _ -> Options.fatal "%s: unexpected case" __LOC__
+  in
+  let _, o1 = Cil.removeOffsetLval lv1
+  and _, o2 = Cil.removeOffsetLval lv2
+  in
+  assert (LLMap.is_sub_offset o1 o2);
+  f_diff_offset o1 o2
+
+let rec create_vertex lv x =
+  Options.debug ~level:9 "creating a vertex for %a" Lval.pretty lv;
+  assert (not (LLMap.mem lv x.lmap));
+  begin
+    match lv with
+      (Mem e, NoOffset) ->
+      (* special case, when we also add another vertex and a points-to edge*)
+      begin
+        (* first find the vertex corresponding to e *)
+        match LvalOrRef.from_exp e with
+        | None -> Options.fatal "unexpected result: Lval.from (%a) = None" Exp.pretty e
+        | Some (LvalOrRef.Ref _) -> Options.fatal "unexpected: *(&x)"
+        | Some (LvalOrRef.Lval lv1) ->
+          (* find the vertex *)
+          let v1, x = find_or_create_vertex (LvalOrRef.Lval lv1) x in
+          (* then creates a vertex for bvl ONLY IF there is no successor *)
+          begin
+            match G.succ x.graph v1 with
+              [] ->
+              let v2, x = create_vertex_simple lv x in
+              (* finally add a points-to edge between v1 and v2 *)
+              let new_graph = G.add_edge x.graph v1 v2 in
+              v2, {x with graph = new_graph }
+            | [succ_v1] ->
+              (* if there is a successor, update lmap and vmap to add blv to that successor's set *)
+              let new_lmap = LLMap.add lv succ_v1 x.lmap in
+              let new_vmap = VMap.add succ_v1 (LSet.add lv (VMap.find succ_v1 x.vmap)) x.vmap in
+              succ_v1, {x with lmap = new_lmap ; vmap = new_vmap }
+            | _ -> Options.fatal " Invariant violated : more than 1 successor"
+          end
+      end
+    | _ -> create_vertex_simple lv x
+  end
+
+and find_or_create_lval_vertex (lv:lval) (x:t) : V.t * t =
+  try LLMap.find lv x.lmap, x
+  with Not_found ->
+    (* try to find if an alias already exists in x *)
+    let map_predecessors : V.t LMap.t =
+      LLMap.find_upper_offsets lv x.lmap
+    in
+    (* for any predecessor, find all its aliases and then look for potential existing vertex *)
+    let f_fold_lmap lvx vx acc =
+      let set_aliases = VMap.find vx x.vmap in
+      Options.debug ~level:9 "looking for aliases of %a in set %a" Lval.pretty lv LSet.pretty set_aliases;
+      if LSet.cardinal set_aliases <= 1 then acc else
+        let off = diff_offset lvx lv in
+        let f_fold_lset lvs acc =
+          try
+            let lvs = Cil.addOffsetLval off lvs in
+            VSet.add (LLMap.find lvs x.lmap) acc
+          with
+            Not_found -> acc
+        in
+        LSet.fold f_fold_lset set_aliases acc
+    in
+    (* set of all existing aliases *)
+    let vset_res = LMap.fold f_fold_lmap map_predecessors VSet.empty in
+    Options.debug ~level:9 "found aliases of %a : %a" Lval.pretty lv VSet.pretty vset_res;
+    if VSet.is_empty vset_res
+    then create_vertex lv x
+    else
+      let () = assert (VSet.cardinal vset_res = 1) in
+      let v_res = VSet.choose vset_res in
+      (* vertex found, update the tables *)
+      let new_lmap = LLMap.add lv v_res x.lmap in
+      let new_vmap = VMap.add v_res (LSet.add lv (VMap.find v_res x.vmap)) x.vmap in
+      v_res, {x with lmap = new_lmap; vmap = new_vmap}
+
+(* find the vertex of an lval *)
+and find_or_create_vertex (lv : LvalOrRef.t) (x:t) : V.t * t =
+  match lv with
+  | LvalOrRef.Lval lv -> find_or_create_lval_vertex lv x
+  | LvalOrRef.Ref lv ->
+    Options.debug ~level:9 "creating a vertex for %a" LvalOrRef.pretty (LvalOrRef.Ref lv);
+    let v1, x = find_or_create_lval_vertex lv x in
+    let va, x = create_cst_vertex x in
+    va, {x with graph = G.add_edge x.graph va v1}
+
+(* TODO is there a better way to do it ? *)
+let find_vertex lv x =
+  let lv = Lval.simplify lv in
+  let v,x1 = find_or_create_lval_vertex lv x in
+  if x == x1
+  (* if x has not been modified, then the vertex was found, not created *)
+  then v
+  else raise Not_found
+
+(* merge of two vertices; the first vertex carries both sets, the second is removed from the graph and from lmap and vmap *)
+let merge x v1 v2 =
+  if (V.equal v1 v2) || not (G.mem_vertex x.graph v1) || not (G.mem_vertex x.graph v2)
+  then x
+  else
+    let set1 = find_lset v1 x in
+    let set2 = find_lset v2 x in
+
+    let new_set = LSet.union set1 set2 in
+    (* update lmap : every lval in v2 must now be associated with v1*)
+    let new_lmap = LSet.fold (fun lv2 m -> LLMap.add lv2 v1 m) set2 x.lmap in
+
+    (* update vmap *)
+    let new_vmap = VMap.add v1 new_set (VMap.remove v2 x.vmap) in
+    (* update the graph *)
+    let f_fold_succ v_succ (g:G.t) : G.t =
+      G.add_edge g v1 v_succ
+    and f_fold_pred v_pred (g:G.t) : G.t =
+      G.add_edge g v_pred v1
+    in
+    let g = x.graph in
+    (* adds all new edges *)
+    let g = G.fold_succ f_fold_succ g v2 g in
+    let g = G.fold_pred f_fold_pred g v2 g in
+    (* remove v2 *)
+    let g =  G.remove_vertex g v2 in
+    {graph = g; lmap = new_lmap; vmap = new_vmap}
+
+(* functions join and unify-pointer of steensgaard's paper *)
+let rec join_without_check (x:t) (v1:V.t) (v2:V.t) : t =
+  if (V.equal v1 v2) || not (G.mem_vertex x.graph v1 && G.mem_vertex x.graph v2)
+  then
+    x
+  else
+    let pt1 = G.succ x.graph v1 in (* TODO ask frama-c type instead of looking in the graph *)
+    let pt2 = G.succ x.graph v2 in
+    let x = merge x v1 v2 in
+    assert (not (G.mem_vertex x.graph v2));
+    match (pt1, pt2) with
+    | [], _ -> x
+    | _, [] -> x
+    | [succ_v1],[succ_v2] ->
+      assert (succ_v1 <> v2);
+      assert (succ_v2 <> v1);
+      join_without_check x succ_v1 succ_v2
+    | _, _ ->
+      Options.fatal "invariant broken"
+
+(* since the recursive version of join, unify, unify2 and merge may break the invariants *)
+let join (x:t) (v1:V.t) (v2:V.t) : t =
+  Options.debug ~level:7 "graph before join(%d,%d):@;<2>@[%a@]" v1 v2 print_debug x;
+  assert_invariants x;
+  let res = join_without_check x v1 v2 in
+  Options.debug ~level:7 "graph after join(%d,%d):@;<2>@[%a@]" v1 v2 print_debug res;
+  begin
+    try assert_invariants res
+    with Assert_failure _ ->
+      Options.debug "join(%d,%d) failed" v1 v2;
+      Options.debug "graph before join(%d,%d):@;<2>@[%a@]" v1 v2 print_debug x;
+      Options.debug "graph after join(%d,%d):@;<2>@[ %a@]" v1 v2 print_debug res;
+      assert_invariants res
+  end;
+  res
+
+let merge_set (x:t) (vs:VSet.t) : V.t * t =
+  let v0 = VSet.choose vs in
+  if VSet.cardinal vs < 2 then v0, x else begin
+    Options.debug ~level:7 "graph before merge_set %a:@;<2>@[%a@]" VSet.pretty vs print_debug x;
+    assert (G.mem_vertex x.graph v0);
+    let result = VSet.fold (fun v acc -> merge acc v0 v) vs x in
+    Options.debug ~level:7 "graph after merge_set %a:@;<2>@[%a@]" VSet.pretty vs print_debug result;
+    v0, result
+  end
+
+let rec join_succs (x:t) v =
+  Options.debug ~level:8 "joining successors of %d" v;
+  if not @@ G.mem_vertex x.graph v then x else
+    match G.succ x.graph v with
+    | [] | [_] -> x
+    | succs ->
+      let v0, x = merge_set x @@ VSet.of_list succs in
+      join_succs x v0
+
+(* in Steensgard's paper, this is written settype(v1,ref(v2,bot)) *)
+let set_type (x:t) (v1:V.t) (v2:V.t) : t =
+  assert_invariants x;
+  (* if v1 points to another node, suppress current outgoing edge (and the node if it is a constant node) *)
+  let g, new_vmap =
+    match G.succ x.graph v1 with
+      [] -> x.graph, x.vmap
+    | [v2] ->
+      (* if v2 is a constant node supress it directly *)
+      if LSet.is_empty (VMap.find v2 x.vmap)
+      then (G.remove_vertex x.graph v2, VMap.remove v2 x.vmap)
+      else (G.remove_edge x.graph v1 v2, x.vmap)
+    | _ -> Options.fatal "too many outgoing edges in set_type"
+  in
+  let new_g = G.add_edge g v1 v2 in
+  let new_x = {x with graph = new_g ; vmap = new_vmap} in
+  assert_invariants new_x ; new_x
+
+let assignment (a:t) (lv:lval) (e:exp) : t =
+  assert_invariants a;
+  if not @@ Cil.isPointerType (Cil.typeOf e) then a else
+    let x = Lval.simplify lv in
+    match LvalOrRef.from_exp e with
+    | None -> a
+    | Some y ->
+      let (v1,a) = find_or_create_lval_vertex x a in
+      let (v2,a) = find_or_create_vertex y a in
+      if List.mem v2 (G.succ a.graph v1) || List.mem v1 (G.succ a.graph v2)
+      then
+        let () =
+          Options.warning ~source:(fst e.eloc)
+            "ignoring assignment of the form: %a = %a"
+            Printer.pp_lval lv Printer.pp_exp e;
+        in a
+      else
+        let a = join a v1 v2 in
+        let () = assert_invariants a in
+        a
+
+(* assignment x = allocate(y) *)
+let assignment_x_allocate_y (a:t) (lv:lval) : t =
+  assert_invariants a;
+  let x = Lval.simplify lv in
+  let (v1,a) = find_or_create_lval_vertex x a in
+  match G.succ a.graph v1 with
+  | [] ->
+    let (v2,a) = create_cst_vertex a in
+    let new_a : t = set_type a v1 v2 in
+    let () = assert_invariants new_a in new_a
+  | [_v2] -> a
+  | _ -> Options.fatal "this should not hapen (invariant broken)"
+
+let is_included (a1:t) (a2:t) =
+  (* tests if a1 is included in a2, at least as the nodes with lval *)
+  assert_invariants a1;
+  assert_invariants a2;
+  Options.debug ~level:8 "testing equal %a AND à.%a" (pretty ~debug:true) a1 (pretty ~debug:true) a2;
+  let exception Not_included in
+  try
+    let iter_lmap (lv : lval) (v1:V.t): unit =
+      let v2 : V.t = try LLMap.find lv a2.lmap with Not_found -> raise Not_included in
+      match G.succ a1.graph v1, G.succ a2.graph v2 with
+        [], _ -> ()
+      | [_], [] -> raise Not_included
+      | [v1p], [v2p] ->
+        if LSet.subset (VMap.find v1p a1.vmap) (VMap.find v2p a2.vmap)
+        then
+          ()
+        else
+          raise Not_included
+      | _ -> Options.fatal "this should not hapen (invariant broken)"
+    in
+    LLMap.iter iter_lmap a1.lmap; true
+  with
+    Not_included -> false
+
+let empty :t =
+  {graph = G.empty; lmap = LLMap.empty; vmap = VMap.empty}
+
+let is_empty s =
+  compare s empty = 0
+
+(* add an int to all vertex values *)
+let shift (a : t) : t =
+  assert_invariants a;
+  if is_empty a then a else
+    let () = Options.debug ~level:8 "before shift: node_counter=%d@.%a" !node_counter print_debug a in
+    let max_idx = G.fold_vertex max a.graph 0 in
+    let min_idx = G.fold_vertex min a.graph max_idx in
+    let offset = !node_counter - min_idx in
+    let shift x = x + offset in
+    let shift_vmap shift_elem vmap =
+      VMap.of_seq @@ Stdlib.Seq.map shift_elem @@ VMap.to_seq vmap
+    in
+    let {graph; lmap; vmap} = a in
+    node_counter := max_idx + offset + 1;
+    let result =
+      {graph = G.map_vertex shift graph;
+       lmap = LLMap.map shift lmap;
+       vmap = shift_vmap (fun (key, l) -> (shift key, l)) vmap}
+    in
+    let () = Options.debug ~level:8 "after shift: node_counter=%d@.%a" !node_counter print_debug result in
+    assert_invariants result;
+    result
+
+let union_find vmap intersections =
+  let module Store : UnionFind.STORE = UnionFind.StoreMap.Make (VMap) in
+  let module UF = UnionFind.Make (Store) in
+  let uf = UF.new_store () in
+  let refs = VMap.mapi (fun i _ -> UF.make uf i) vmap in
+  let put_into_uf (v1,v2) =
+    let r1 = VMap.find v1 refs in
+    let r2 = VMap.find v2 refs in
+    ignore @@ UF.union uf r1 r2
+  in
+  let _vs = Seq.iter put_into_uf intersections in
+  let sets_to_be_joined =
+    let add_to_map i r sets =
+      let repr = UF.find uf r in
+      let add_to_set = function
+        | None -> Some (VSet.singleton i)
+        | Some set -> Some (VSet.add i set)
+      in
+      VMap.update (UF.get uf repr) add_to_set sets
+    in
+    VMap.fold add_to_map refs VMap.empty in
+  sets_to_be_joined
+
+let union (a1:t) (a2:t) :t =
+  (* naive algorithm :
+     1 merge the graph and the vmap (by doing union of sets)
+     2 for any node present in both a1.graph and a2.graph, merge/join them
+     3 for any lval [lv] that are has an entry in both a1.lmap and a2.lmap, merge the two vertex a1.lmap[lv]
+       and a2.lmap[lv]
+
+     I am not confident about this function, there are too many potential bugs and inefficiencies
+  *)
+  assert_invariants a1;
+  assert_invariants a2;
+
+  Options.debug ~level:4 "Union: First graph:%a" print_graph a1;
+  Options.debug ~level:5 "Union: First graph:%a" print_debug a1;
+  Options.debug ~level:4 "Union: Second graph:%a" print_graph a2;
+  Options.debug ~level:5 "Union: Second graph:%a" print_debug a2;
+  let new_graph =
+    G.fold_vertex
+      (fun v2 g -> G.add_vertex g v2)
+      a2.graph
+      a1.graph
+  in
+  let new_graph =
+    G.fold_edges
+      (fun v2a v2b g -> G.add_edge g v2a v2b)
+      a2.graph
+      new_graph
+  in
+  let new_vmap =
+    VMap.union (fun _ lset1 lset2 -> Option.some @@ LSet.union lset1 lset2)
+      a2.vmap
+      a1.vmap
+  in
+  let sets_to_be_joined =
+    let intersections = LLMap.to_seq @@ LLMap.intersect a1.lmap a2.lmap in
+    union_find new_vmap @@ Seq.map (fun (_,_,x) -> x) intersections
+  in
+  let new_lmap = LLMap.union a1.lmap a2.lmap in
+  Options.debug ~level:7 "Union: sets to be joined:@[";
+  VMap.iter (fun _ set -> Options.debug ~level:7 "%a" VSet.pretty set) sets_to_be_joined;
+  Options.debug ~level:7 "@]";
+  let new_a = {graph = new_graph; lmap = new_lmap; vmap = new_vmap} in
+  let merged_nodes, new_a =
+    VMap.fold
+      (fun _ set (merged_nodes, x) -> let v0, x = merge_set x set in (v0 :: merged_nodes), x)
+      sets_to_be_joined
+      ([], new_a)
+  in
+  let new_a = List.fold_left join_succs new_a merged_nodes in
+  Options.debug ~level:4 "Union: Result graph:%a" print_graph new_a;
+  Options.debug ~level:5 "Union: Result graph:%a" print_debug new_a;
+  begin
+    try assert_invariants new_a
+    with Assert_failure _ ->
+      Options.debug "union failed";
+      Options.debug "Union: First graph:%a" print_graph a1;
+      Options.debug "Union: First graph:%a" print_debug a1;
+      Options.debug "Union: Second graph:%a" print_graph a2;
+      Options.debug "Union: Second graph:%a" print_debug a2;
+      Options.debug "Union: Result graph:%a" print_graph new_a;
+      Options.debug "Union: Result graph:%a" print_debug new_a;
+      assert_invariants new_a
+  end;
+  new_a
+
+(** a type for summaries of functions *)
+type summary =
+  {
+    state : t option;
+    formals: lval list;
+    locals: lval list;
+    return : exp option
+  }
+
+let make_summary (s : t) (kf : kernel_function) =
+  let exp_return : exp option =
+    if Kernel_function.has_definition kf then
+      let return_stmt = Kernel_function.find_return kf in
+      match return_stmt.skind with
+        Return (e, _) -> e
+      | _ -> Options.fatal "this should not happen"
+    else
+      None
+  in
+  let s =
+    match exp_return with
+      None -> s
+    | Some e ->
+      begin
+        match s, LvalOrRef.from_exp e with
+          _, None -> s
+        | s, Some lv ->
+          let _, new_s = find_or_create_vertex lv s in
+          new_s
+      end
+  in
+  {
+    state = Some s;
+    formals = List.map (fun v -> (Var v,NoOffset)) (Kernel_function.get_formals kf);
+    locals = List.map (fun v -> (Var v,NoOffset))  (Kernel_function.get_locals kf);
+    return = exp_return
+  }
+
+let pretty_summary ?(debug=false) fmt s =
+  let print_list_lval ~state fmt (l: lval list) =
+    let is_first = ref true in
+    let print_elem x =
+      if !is_first then is_first := false else Format.fprintf fmt "@  ";
+      Format.fprintf fmt "@[%a" Cil_datatype.Lval.pretty x;
+      let pointees = points_to_set x state in
+      if not @@ LSet.is_empty pointees then
+        Format.fprintf fmt "→%a" LSet.pretty pointees;
+      Format.fprintf fmt "@]";
+    in
+    List.iter print_elem l
+  in
+  let print_option pp fmt x =
+    match x with
+    | Some x -> pp fmt x
+    | None -> Format.fprintf fmt "<none>"
+  in
+  match s.state with
+  | None -> if debug then Format.fprintf fmt "not found"
+  | Some s when is_empty s -> if debug then Format.fprintf fmt "empty"
+  | Some state ->
+    begin
+      Format.fprintf fmt "@[formals: @[%a@]@;<4>locals: @[%a@]@;<4>returns: @[%a@]@;<4>state: @[%a@] "
+        (print_list_lval ~state) s.formals
+        (print_list_lval ~state) s.locals
+        (print_option Exp.pretty) s.return
+        (print_option @@ pretty ~debug) s.state;
+    end
+
+(* the algorithm:
+   - unify the two graphs dropping all the variables from the summary
+   - pair arguments with formals assigning the formal's successor as the argument's successor
+*)
+let call (state:t) (res:lval option) (args:exp list) (summary:summary) :t =
+  assert_invariants state;
+  let formals = summary.formals in
+  assert (List.length args = List.length formals);
+  let sum_state = shift @@ Option.get summary.state in
+
+  (* pair up formals and their corresponding arguments,
+     as well as the bound result with the returned value *)
+  let arg_formal_pairs =
+    let res_ret = match res, summary.return with
+      | None, None -> []
+      | Some res, Some ret ->
+        let simplify_ret x = match LvalOrRef.from_exp x with
+          | Some (LvalOrRef.Lval lval) -> lval
+          | _ -> Options.fatal "unexpected form of return statement"
+        in
+        [LvalOrRef.Lval (Lval.simplify res), simplify_ret ret]
+      | None, Some _ -> []
+      | Some _, None -> (* Shouldn't happen: Frama-C adds missing returns *)
+        Options.fatal "unexpected case: result without return"
+    in
+    let simplify_both (arg, formal) =
+      try
+        match LvalOrRef.from_exp arg with
+        | None -> None
+        | Some lv -> Some (lv, Lval.simplify formal)
+      with Explicit_pointer_address loc ->
+        Options.warning ~source:(fst loc) ~wkey:Options.Warn.unsupported_address
+          "unsupported feature: explicit pointer address: %a; analysis may be unsound"
+          Printer.pp_exp arg;
+        None
+    in
+    res_ret @ List.filter_map simplify_both @@ List.combine args formals
+  in
+
+  (* for each pair (lv1,lv2) find (or create) the corresponding vertices *)
+  let state, vertex_pairs =
+    let state = ref state in
+    let find_vertex (lv1, lv2) =
+      try
+        let v2 = LLMap.find lv2 sum_state.lmap in
+        let v1, new_state = find_or_create_vertex lv1 !state in
+        state := new_state;
+        Some (v1, v2)
+      with Not_found -> None
+    in
+    !state, List.filter_map find_vertex arg_formal_pairs
+  in
+
+  (* merge the function graph;
+     for every arg/formal vertex pair (v1,v2) and every edge v2→v create edge v1→v. *)
+  let g =
+    let transfer_succs (g : G.t) (v1,v2) =
+      let v2_succs = G.succ sum_state.graph v2 in
+      assert (List.length v2_succs < 2);
+      List.fold_left (fun g succ -> G.add_edge g v1 succ) g v2_succs
+    in
+    let g = state.graph in
+    let g = G.fold_vertex (fun i g -> G.add_vertex g i) sum_state.graph g in
+    let g = G.fold_edges (fun i j g -> G.add_edge g i j) sum_state.graph g in
+    List.fold_left transfer_succs g vertex_pairs
+  in
+
+  (* garbage collect: remove leaf vertices from g that originate from sum_state *)
+  let vertices_to_add_to_g, g =
+    let g = ref g in
+    let remove_if_leaf v _ =
+      if G.in_degree sum_state.graph v = 0
+      then let () = g := G.remove_vertex !g v in None
+      else Some LSet.empty
+    in
+    let remaining_vertices = VMap.filter_map remove_if_leaf sum_state.vmap in
+    remaining_vertices, !g
+  in
+
+  let state = {
+    graph = g;
+    lmap = state.lmap;
+    vmap =
+      let left_bias _ l _ = Some l in
+      VMap.union left_bias state.vmap vertices_to_add_to_g}
+  in
+
+  let state = List.fold_left join_succs state (List.map fst vertex_pairs) in
+
+  assert_invariants state;
+  state
diff --git a/src/plugins/alias/abstract_state.mli b/src/plugins/alias/abstract_state.mli
new file mode 100644
index 0000000000000000000000000000000000000000..8506611bc0f61251f5ee4b60f44506145c9fff96
--- /dev/null
+++ b/src/plugins/alias/abstract_state.mli
@@ -0,0 +1,141 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2023                                               *)
+(*    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 abstract_state *)
+
+open Cil_types
+
+(** Points-to graphs datastructure. *)
+module G: Graph.Sig.G
+
+(** Set of [lval]s. Differs from Cil_datatype.Lval.Set in that is uses a
+    different comparison function ([Cil_datatype.LvalStructEq.compare]). *)
+module LSet : sig
+  include Set.S with type elt = lval
+
+  val pretty: Format.formatter -> t -> unit
+end
+
+(** map of [lval]s. Differs from Cil_datatype.Lval.Met in that is uses a
+    different comparison function ([Cil_datatype.LvalStructEq.compare]). *)
+module LMap : sig
+  include Map.S with type key = lval
+
+  val pretty: (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a t -> unit
+end
+
+(** external signature *)
+module type S =
+sig
+
+  (** Type denothing an abstract state of the analysis. It is a graph containing
+      all aliases and points-to information. *)
+  type t
+
+  (** access to the points-to graph *)
+  val get_graph: t -> G.t
+
+  (** set of lvals stored in a vertex *)
+  val get_lval_set : G.V.t -> t -> LSet.t
+
+  (** pretty printer; debug=true prints the graph, debug = false only
+      prints aliased variables *)
+  val pretty : ?debug:bool -> Format.formatter -> t -> unit
+
+  (** dot printer; first argument is a file name *)
+  val print_dot : string -> t -> unit
+
+  (** finds the vertex corresponding to a lval. May raise @Not_found
+  *)
+  val find_vertex : lval -> t -> G.V.t
+
+  (** same as previous function, but return a set of lval. Cannot
+      raise an exception but may return an empty set if the lval is not
+      in the graph *)
+  val find_aliases : lval -> t -> LSet.t
+
+  (** similar to the previous functions, but does not only give the
+      equivalence class of lv, but also all lv that are aliases in
+      other vertex of the graph *)
+  val find_all_aliases : lval -> t -> LSet.t
+
+  (** the set of all lvars to which the given variable may point. *)
+  val points_to_set : lval -> t -> LSet.t
+
+  (** find_aliases, then recursively finds other sets of lvals. We
+      have the property (if lval [lv] is in abstract state [x]) :
+      List.hd (find_transitive_closure lv x) = (find_vertex lv x,
+      find_aliases lv x) *)
+  val find_transitive_closure : lval -> t -> (G.V.t * LSet.t) list
+
+  (** inclusion test; [is_included a1 a2] tests if, for any lvl
+      present in a1 (associated to a vertex v1), that it is also
+      present in a2 (associated to a vertex v2) and that
+      get_lval_set(succ(v1) is included in get_lval_set(succ(v2)) *)
+  val is_included : t -> t -> bool
+
+end
+
+
+include S
+
+(** check all the invariants that must be true on an abstract value
+      before and after each function call or transformation of the graph)  *)
+val assert_invariants : t -> unit
+
+(** Functions for Steensgaard's algorithm, see the paper *)
+val join : t -> G.V.t -> G.V.t -> t
+
+(** transfert functions for different kinds of assignments *)
+val assignment : t -> lval -> exp -> t
+
+(** transfert function for malloc calls *)
+val assignment_x_allocate_y : t -> lval -> t
+
+
+(** inclusion test; [is_included a1 a2] tests if, for any lvl present
+    in a1 (associated to a vertex v1), that it is also present in a2
+    (associated to a vertex v2) and that set(succ(v1) is included in
+    set(succ(v2)) *)
+val is_included : t -> t -> bool
+
+(** union of two abstract values ; ensures that if 2 lval are
+    aliased in one of the two input graph (or in a points-to
+    relationship), then they will also be aliased/points-to in the
+    result *)
+val union : t -> t -> t
+
+(** empty graph *)
+val empty : t
+
+(** Type denoting summaries of functions *)
+type summary
+
+(** creates a summary from a state and a function *)
+val make_summary : t -> kernel_function -> summary
+
+(** pretty printer *)
+val pretty_summary :  ?debug:bool -> Format.formatter -> summary -> unit
+
+(** [call a res args s] computes the abstract state after the
+    instruction res=f(args), with f summarized by [s]. [a] is the abstract state before the call *)
+val call: t -> lval option -> exp list -> summary -> t
diff --git a/src/plugins/alias/analysis.ml b/src/plugins/alias/analysis.ml
new file mode 100644
index 0000000000000000000000000000000000000000..148dabcd63c02521a4a2059b661b4b21af6b5c60
--- /dev/null
+++ b/src/plugins/alias/analysis.ml
@@ -0,0 +1,330 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2023                                               *)
+(*    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
+
+module Dataflow = Dataflow2
+
+module type Table = sig
+  type key
+  type value
+  val find: key -> value
+  (** @raise Not_found if the key is not in the table. *)
+end
+
+module type InternalTable = sig
+  include Table
+  val add : key -> value -> unit
+  val iter : (key -> value -> unit) -> unit
+end
+
+module Make_table (H: Hashtbl.S) (V: sig type t val size : int end)
+  : InternalTable with type key = H.key and type value = V.t = struct
+  type key = H.key
+  type value = V.t
+  let tbl = H.create V.size
+  let add = H.replace tbl
+  let find = H.find tbl
+  let iter f = H.iter f tbl
+end
+
+(* In Function_table, value None means the function has no definition *)
+module Function_table = Make_table (Kernel_function.Hashtbl) (struct
+    type t = Abstract_state.summary option
+    let size = 7
+  end)
+
+let function_compute_ref = Extlib.mk_fun "function_compute"
+
+(* In Stmt_table, value None means abstract state = Bottom *)
+module Stmt_table = struct
+  include Dataflow.StartData (struct
+      type t = Abstract_state.t option
+      let size = 7
+    end)
+  type key = stmt
+  type value = data
+end
+
+let warn_unsupported_explicit_pointer pp_obj obj loc =
+  Options.warning ~source:(fst loc) ~wkey:Options.Warn.unsupported_address
+    "unsupported feature: explicit pointer address: %a; analysis may be unsound" pp_obj obj
+
+let do_assignment (lv:lval) (exp:exp) (a:Abstract_state.t) : Abstract_state.t =
+  try Abstract_state.assignment a lv exp
+  with Simplified.Explicit_pointer_address loc ->
+    warn_unsupported_explicit_pointer  Printer.pp_exp exp loc;
+    a
+
+let rec do_init (lv:lval) (init:init) state =
+  match init with
+  | SingleInit e -> Option.map (do_assignment lv e) state
+  | CompoundInit (_, l) ->
+    List.fold_left (fun state (o, init) -> do_init (Cil.addOffsetLval o lv) init state) state l
+
+let doFunction f = !function_compute_ref f
+
+let do_function_call (stmt:stmt) state (res : lval option) (ef : exp) (args: exp list) loc =
+  let is_malloc (s:string) : bool =
+    (s = "malloc") || (s = "calloc") (* todo : add all function names *)
+  in
+  match ef with
+  | {enode=Lval (Var v, _);_}  when is_malloc v.vname ->
+    begin
+      (* special case for malloc *)
+      match (state,res) with
+        (None, _) -> None
+      | (Some a, None) -> (Options.warning "Memory allocation not stored (ignored)"; Some a)
+      | (Some a, Some lv) ->
+        try Some (Abstract_state.assignment_x_allocate_y a lv)
+        with Simplified.Explicit_pointer_address loc ->
+          warn_unsupported_explicit_pointer Printer.pp_stmt stmt loc;
+          Some a
+    end
+  | _ ->
+    begin
+      (* general case *)
+      let summary =
+        match Kernel_function.get_called ef with
+        | Some kf when Kernel_function.is_main kf -> None
+        | Some kf -> begin
+            try Function_table.find kf
+            with Not_found -> doFunction kf
+          end
+        | None ->
+          Options.warning ~wkey:Options.Warn.unsupported_function ~source:(fst loc)
+            "unsupported feature: call to function pointer: %a" Exp.pretty ef;
+          None
+      in
+      match (state, summary) with
+        (None, _) -> None
+      | (Some a, Some summary) ->
+        Some (Abstract_state.call a res args summary)
+      | (Some a, None) ->
+        Options.warning ~wkey:Options.Warn.undefined_function ~once:true ~source:(fst loc)
+          "function %a has no definition" Exp.pretty ef;
+        Some a
+    end
+
+let do_cons_init (s:stmt) (v:varinfo) f arg t loc state =
+  Cil.treat_constructor_as_func (do_function_call s state) v f arg t loc
+
+let analyse_instr (s:stmt)  (i:instr) (a:Abstract_state.t option) : Abstract_state.t option =
+  match i with
+    Set (lv,exp,_) -> Option.map (do_assignment lv exp) a
+  | Local_init (v,AssignInit i,_) -> do_init (Var v, NoOffset) i a
+  | Local_init (v,ConsInit (f,arg,t),loc) -> do_cons_init s v f arg t loc a
+  | Code_annot _ -> a
+  | Skip _ -> a
+  | Call (res,ef,es,loc) -> (* !function_compute_ref ef *)
+    do_function_call s a res ef es loc
+  | Asm (_,_,_,loc) ->
+    Options.warning
+      ~source:(fst loc) ~wkey:Options.Warn.unsupported_asm
+      "unsupported feature: assembler code; skipping";
+    a
+
+let pp_abstract_state_opt ?(debug=false) fmt v =
+  match v with
+  | None -> Format.fprintf fmt "⊥"
+  | Some a -> Abstract_state.pretty ~debug fmt a
+
+let do_instr (s:stmt)  (i:instr) (a:Abstract_state.t option) : Abstract_state.t option =
+  Options.feedback ~level:3 "@[analysing instruction:@ %a@]" Printer.pp_stmt s;
+  let result = analyse_instr s i a in
+  Options.feedback ~level:3 "@[May-aliases after instruction@;<2>@[%a@]@;<2>are@;<2>@[%a@]@]"
+    Printer.pp_stmt s (pp_abstract_state_opt ~debug:false) result;
+  Options.debug ~level:3 "@[May-alias graph after instruction@;<2>@[%a@]@;<2>is@;<4>@[%a@]@]"
+    Printer.pp_stmt s (pp_abstract_state_opt ~debug:true) result;
+  result
+
+module T = struct
+  let name = "alias"
+
+  let debug = true (* TODO see options *)
+
+  type t = Abstract_state.t option
+
+  module StmtStartData = Stmt_table
+
+  let copy x = x (* we only have persistant data *)
+
+  let pretty fmt a =
+    match a with
+      None -> Format.fprintf fmt "<No abstract state>"
+    | Some a -> Abstract_state.pretty fmt a
+
+  let computeFirstPredecessor _ a = a
+
+  let combinePredecessors _stmt ~old state =
+    match old, state with
+    | _, None -> assert false
+    | None, Some _ -> Some state (* [old] already included in [state] *)
+    | Some old, Some new_ ->
+      if Abstract_state.is_included new_ old then
+        None
+      else
+        Some (Some (Abstract_state.union old new_))
+
+  let doInstr = do_instr
+
+  let doGuard _ _ a =
+    Dataflow.GUse a, Dataflow.GUse a
+
+  let doStmt _ _ = Dataflow.SDefault
+
+  let doEdge _ _ a = a
+end
+
+module F = Dataflow.Forwards (T)
+
+let do_stmt (a: Abstract_state.t) (s:stmt) :  Abstract_state.t =
+  match s.skind with
+    Instr i ->
+    begin
+      match do_instr s i (Some a) with
+        None -> Options.fatal "problem here"
+      | Some a -> a
+    end
+  | _ -> a
+
+let analyse_function (kf:kernel_function) =
+  Options.feedback ~level:2 "analysing function: %a" Kernel_function.pretty kf;
+  if Kernel_function.has_definition kf then
+    begin
+      let first_stmt =
+        try Kernel_function.find_first_stmt kf
+        with Kernel_function.No_Statement -> assert false
+      in
+      T.StmtStartData.add first_stmt (Some Abstract_state.empty);
+      F.compute [first_stmt];
+      let return_stmt = Kernel_function.find_return kf in
+      try Stmt_table.find return_stmt
+      with Not_found ->
+        begin
+          let source, _ = Kernel_function.get_location kf in
+          Options.warning ~source ~wkey:Options.Warn.no_return_stmt
+            "function %a does not return; analysis may be unsound"
+            Kernel_function.pretty kf;
+          Some Abstract_state.empty
+        end
+    end
+  else
+    None
+
+let doFunction (kf:kernel_function) =
+  let final_state = analyse_function kf in
+  let level = if Kernel_function.is_main kf then 1 else 2 in
+  Options.feedback ~level "@[May-aliases at the end of function %a:@ @[%a@]"
+    Kernel_function.pretty kf
+    (pp_abstract_state_opt ~debug:false) final_state;
+  Options.debug ~level "May-alias graph at the end of function %a:@;<4>@[%a@]"
+    Kernel_function.pretty kf
+    (pp_abstract_state_opt ~debug:true) final_state;
+  let result =
+    match final_state with
+    (* final state is None if kf has no definition *)
+      None -> None
+    | Some fs ->
+      let summary = Abstract_state.make_summary fs kf in
+      Options.debug ~level:2 "Summary of function %a:@ @[%a@]"
+        Kernel_function.pretty kf
+        (Abstract_state.pretty_summary ~debug:false) summary;
+      Some summary
+  in
+  if Kernel_function.is_main kf then begin
+    match Options.Dot_output.get (), final_state with
+    | "", _ -> ()
+    | _, None -> ()
+    | fname, Some final_state -> Abstract_state.print_dot fname final_state
+  end;
+  Function_table.add kf result;
+  result
+
+let () = function_compute_ref := doFunction
+
+let make_summary (state:Abstract_state.t) (kf:kernel_function) =
+  try
+    begin
+      match Function_table.find kf with
+        Some s -> (state, s)
+      | None -> Options.fatal "not implemented"
+    end
+  with
+    Not_found ->
+    begin
+      match doFunction kf with
+        Some s -> (state, s)
+      | None -> Options.fatal "not implemented"
+    end
+
+let computed_flag = ref false
+
+let is_computed () = !computed_flag
+
+let print_stmt_table_elt fmt k v :unit =
+  let print_key = Stmt.pretty in
+  let print_value fmt v =
+    match v with
+    | None -> Format.fprintf fmt "<Bot>"
+    | Some a -> Abstract_state.pretty ~debug:(Options.DebugTable.get ()) fmt a
+  in
+  Format.fprintf fmt "Before statement %a :@[<hov 2> %a@]" print_key k print_value v
+
+let print_function_table_elt fmt kf s : unit =
+  let function_name = Kernel_function.get_name kf in
+  match s with
+  | None -> Options.debug "function %s -> None" function_name
+  | Some s ->
+    Format.fprintf fmt "Summary of function %s:@;<5 2>@[%a@]@."
+      function_name
+      (Abstract_state.pretty_summary ~debug:(Options.DebugTable.get ())) s
+
+let compute () =
+  Ast.compute ();
+  Globals.Functions.iter (fun kf -> ignore @@ doFunction kf);
+  computed_flag := true;
+  if Options.ShowStmtTable.get () then
+    Stmt_table.iter (print_stmt_table_elt Format.std_formatter);
+  if Options.ShowFunctionTable.get () then
+    Function_table.iter (print_function_table_elt Format.std_formatter)
+
+let clear () =
+  computed_flag := false;
+  Stmt_table.clear ()
+
+let get_state_before_stmt _kf stmt =
+  if is_computed ()
+  then
+    try Stmt_table.find stmt with
+      Not_found -> None
+  else
+    None
+
+let get_summary kf =
+  if is_computed ()
+  then
+    try Function_table.find kf with
+      Not_found -> None
+  else
+    None
diff --git a/src/plugins/gui/dgraph_helper.yes.ml b/src/plugins/alias/analysis.mli
similarity index 53%
rename from src/plugins/gui/dgraph_helper.yes.ml
rename to src/plugins/alias/analysis.mli
index 7c506cd2a01e459a98743c651c3ad265a6d209bd..f1bb2652e88fdb27f7c590589b3dcfb6a252438b 100644
--- a/src/plugins/gui/dgraph_helper.yes.ml
+++ b/src/plugins/alias/analysis.mli
@@ -20,41 +20,49 @@
 (*                                                                        *)
 (**************************************************************************)
 
-open DGRAPH_MODULE
-
-let graph_window ~parent ~title make_view =
-  let height = int_of_float (float parent#default_height *. 3. /. 4.) in
-  let width = int_of_float (float parent#default_width *. 3. /. 4.) in
-  let graph_window =
-    GWindow.window
-      ~width ~height ~title ~resizable:true ~position:`CENTER ()
-  in
-  let view = make_view ~packing:graph_window#add () in
-  graph_window#show();
-  view#adapt_zoom();
-  ()
-;;
-
-let graph_window_through_dot ~parent ~title dot_formatter =
-  let make_view ~packing () =
-    let temp_file =
-      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
-    let fmt = Format.formatter_of_out_channel (open_out temp_file) in
-    dot_formatter fmt;
-    Format.pp_print_flush fmt ();
-    let view =
-      snd
-        (DGraphContainer.Dot.from_dot_with_commands ~packing temp_file)
-    in
-    view
-  in
-  try
-    graph_window ~parent ~title make_view
-  with DGRAPH_ERROR _ as exn ->
-    Gui_parameters.error
-      "@[cannot display dot graph:@ %s@]"
-      (Printexc.to_string exn)
+open Cil_types
+
+open Abstract_state
+
+module type Table = sig
+  type key
+  type value
+  val find: key -> value
+  (** @raise Not_found if the key is not in the table. *)
+end
+
+(** Store the graph at each statement. *)
+module Stmt_table: Table with type key = stmt and type value = Abstract_state.t option
+
+
+(** Store the summary of each function. *)
+module Function_table:
+  Table with type key = kernel_function and type value = Abstract_state.summary option
+
+(** [do_stmt a s] computes the abstract state after statement s. This
+    function does NOT store the result in Stmt_table.  *)
+val do_stmt: t -> stmt -> t
+
+(** [make_summary a f] computes the summary of a function (and the
+    next abstract state if needed) and stores the summary in
+    [Function_table]. *)
+val make_summary: t -> kernel_function -> t * summary
+
+(** main analysis functions *)
+
+(** [compute ()] performs the may-alias analysis. It must be done once
+    before using functions defined in API.ml *)
+val compute : unit -> unit
+
+(** [is_computed ()] returns true iff an analysis was done previously *)
+val is_computed : unit -> bool
+
+(** [clear()] clears caches and imperative structures that are used by
+    the analysis. All accumulated data are lost. *)
+val clear : unit -> unit
+
+(** see API.mli *)
+val get_state_before_stmt :  kernel_function -> stmt -> Abstract_state.t option
+
+(** see API.mli *)
+val get_summary : kernel_function -> Abstract_state.summary option
diff --git a/src/plugins/alias/dune b/src/plugins/alias/dune
new file mode 100644
index 0000000000000000000000000000000000000000..63d49ab5cc95c628ad7d0cf25789504a89d9b823
--- /dev/null
+++ b/src/plugins/alias/dune
@@ -0,0 +1,46 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;                                                                        ;;
+;;  This file is part of Frama-C.                                         ;;
+;;                                                                        ;;
+;;  Copyright (C) 2007-2023                                               ;;
+;;    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).            ;;
+;;                                                                        ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+( rule
+  (alias frama-c-configure)
+  (deps (universe))
+  (action ( progn
+            (echo "Alias:" %{lib-available:frama-c-alias.core} "\n")
+            (echo " - Frama-C:" %{lib-available:frama-c.kernel} "\n")
+          )
+  )
+)
+
+( library
+  (name Alias)
+  (public_name frama-c-alias.core)
+  (flags -open Frama_c_kernel :standard)
+  (libraries frama-c.kernel ocamlgraph unionFind)
+  (instrumentation (backend landmarks))
+)
+
+( plugin
+  (optional)
+  (name alias)
+  (libraries frama-c-alias.core)
+  (site (frama-c plugins))
+)
diff --git a/src/plugins/alias/dune-project b/src/plugins/alias/dune-project
new file mode 100644
index 0000000000000000000000000000000000000000..c934d313d775e41dbb3ccc769d0dba2d1439110a
--- /dev/null
+++ b/src/plugins/alias/dune-project
@@ -0,0 +1,25 @@
+(lang dune 3.2)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;                                                                        ;;
+;;  This file is part of Frama-C.                                         ;;
+;;                                                                        ;;
+;;  Copyright (C) 2007-2023                                               ;;
+;;    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).            ;;
+;;                                                                        ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(name frama-c-alias)
+(using dune_site 0.1)
diff --git a/src/plugins/alias/frama-c-alias.opam b/src/plugins/alias/frama-c-alias.opam
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/plugins/alias/options.ml b/src/plugins/alias/options.ml
new file mode 100644
index 0000000000000000000000000000000000000000..4f2fd9582b09ec7e2ab37cc4ae0f185a3334f6a3
--- /dev/null
+++ b/src/plugins/alias/options.ml
@@ -0,0 +1,79 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2023                                               *)
+(*    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).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+(* -------------------------------------------------------------------------- *)
+(* --- Plugin Registration                                                --- *)
+(* -------------------------------------------------------------------------- *)
+
+include Plugin.Register
+    (struct
+      let name = "Alias Analysis"
+      let help = "Lightweight May-Alias Analysis"
+      let shortname = "alias"
+    end)
+
+module Enabled = False
+    (struct
+      let option_name = "-alias"
+      let help = "Enable May-Alias Analyzer"
+    end)
+
+module ShowFunctionTable = False
+    (struct
+      let option_name = "-alias-show-function-table"
+      let help = "display summary for each function at the end of the analysis"
+    end)
+
+module ShowStmtTable = False
+    (struct
+      let option_name = "-alias-show-stmt-table"
+      let help = "display abstract state for each function at the end of the analysis"
+    end)
+
+
+module DebugTable = False
+    (struct
+      let option_name = "-alias-debug-table"
+      let help = "switch to debug mode when printing statement or function tables (with options -alias-show-stmt-table and -alias-show-function-table)"
+    end)
+
+
+module Dot_output =
+  Empty_string
+    (struct
+      let option_name = "-alias-dot-output"
+      let arg_name = "f"
+      let help = "output final abstract state as dot file <f>"
+    end)
+
+module Warn = struct
+  let no_return_stmt = register_warn_category "no-return"
+  let undefined_function = register_warn_category "undefined:fn"
+  let unsupported_address = register_warn_category "unsupported:addr"
+  let unsupported_asm = register_warn_category "unsupported:asm"
+  let unsupported_function = register_warn_category "unsupported:fn"
+  let unsafe_cast = register_warn_category "unsafe-cast"
+end
+
+module DebugKeys = struct
+  let lvals = register_category "lvals"
+end
diff --git a/src/plugins/gui/gtk_compat.mli b/src/plugins/alias/options.mli
similarity index 60%
rename from src/plugins/gui/gtk_compat.mli
rename to src/plugins/alias/options.mli
index 8eaaf3d5fb526978fcb0e38d9edc9779c0f21fb3..bfe5800b537c1a318d743ab9f19ba389a1031700 100644
--- a/src/plugins/gui/gtk_compat.mli
+++ b/src/plugins/alias/options.mli
@@ -20,30 +20,36 @@
 (*                                                                        *)
 (**************************************************************************)
 
-module Pango : sig
-  val set_small_font : #GObj.widget -> unit
-  (** makes the font smaller. *)
+(* -------------------------------------------------------------------------- *)
+(* --- Plugin Registration                                                --- *)
+(* -------------------------------------------------------------------------- *)
 
-  val set_bold_font : #GObj.widget -> unit
-  (** makes the font bold. *)
+include Plugin.S
+
+(** Module activation *)
+module Enabled : Parameter_sig.Bool
+
+(** Displays the table [function -> summary] at the end of the analysis *)
+module ShowFunctionTable : Parameter_sig.Bool
+
+(** Displays the table [statement -> state] at the end of the analysis *)
+module ShowStmtTable : Parameter_sig.Bool
+
+(** Switch to debug mode when displaying tables *)
+module DebugTable : Parameter_sig.Bool
+
+(** Displays the final abstract state in Dot File <f> *)
+module Dot_output : Parameter_sig.String
+
+module Warn : sig
+  val no_return_stmt : warn_category
+  val undefined_function : warn_category
+  val unsupported_address : warn_category
+  val unsupported_asm : warn_category
+  val unsupported_function : warn_category
+  val unsafe_cast : warn_category
 end
 
-val get_toolbar_index: GButton.toolbar -> GButton.tool_item -> int
-
-val window:
-  ?kind:Gtk.Tags.window_type ->
-  ?title:string ->
-  ?decorated:bool ->
-  ?deletable:bool ->
-  ?focus_on_map:bool ->
-  ?icon:GdkPixbuf.pixbuf ->
-  ?icon_name:string ->
-  ?modal:bool ->
-  ?position:Gtk.Tags.window_position ->
-  ?resizable:bool ->
-  ?screen:Gdk.screen ->
-  ?type_hint:Gdk.Tags.window_type_hint ->
-  ?urgency_hint:bool ->
-  ?wmclass:(string * string) ->
-  ?border_width:int ->
-  ?width:int -> ?height:int -> ?show:bool -> unit -> GWindow.window
+module DebugKeys : sig
+  val lvals : category
+end
diff --git a/src/plugins/alias/simplified.ml b/src/plugins/alias/simplified.ml
new file mode 100644
index 0000000000000000000000000000000000000000..8250af8e229b46ebca8acba3184ef2e89bcafaad
--- /dev/null
+++ b/src/plugins/alias/simplified.ml
@@ -0,0 +1,163 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2023                                               *)
+(*    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
+
+let nul_exp= Cil.zero ~loc:Location.unknown
+let is_nul_exp = Cil_datatype.ExpStructEq.equal nul_exp
+
+module HL = Lval.Hashtbl
+module HE = Exp.Hashtbl
+
+let cached_lval = HL.create 23
+let cached_exp = HE.create 37
+
+let clear_cache () =
+  HL.clear cached_lval;
+  HE.clear cached_exp
+
+exception Explicit_pointer_address of location
+
+let check_cast_compatibility e typ =
+  let type_of_e = Cil.typeOf e in
+  (* emit a warning for unsafe casts, but not for the NULL pointer *)
+  if Cil.need_cast typ type_of_e && not (Cil.isZero e) then
+    Options.warning
+      ~once:true
+      ~source:(fst @@ e.eloc)
+      ~wkey:Options.Warn.unsafe_cast
+      "unsafe cast from %a to %a"
+      Printer.pp_typ type_of_e Printer.pp_typ typ
+
+let rec simplify_offset o =
+  match o with
+  | NoOffset -> NoOffset
+  | Field(f,o) -> Field(f, simplify_offset o)
+  | Index(_e,o) -> Index(nul_exp, simplify_offset o)
+
+let rec simplify_lval (h,o) =
+  try HL.find cached_lval (h,o)
+  with Not_found ->
+    let res = (simplify_host h, simplify_offset o) in
+    HL.add cached_lval (h,o) res;
+    res
+
+and simplify_host h =
+  match h with
+  | Var _ -> h
+  | Mem e ->
+    let simp_e = simplify_exp e in
+    if is_nul_exp simp_e
+    then raise (Explicit_pointer_address e.eloc)
+    else Mem simp_e
+
+and simplify_exp e =
+  try
+    HE.find cached_exp e
+  with Not_found ->
+    let res =
+      match e.enode with
+      | CastE (typ, e) ->
+        check_cast_compatibility e typ;
+        simplify_exp e
+      | Lval lv -> {e with enode = Lval (simplify_lval lv)}
+      | AddrOf lv | StartOf lv -> {e with enode = AddrOf (simplify_lval lv)}
+      | BinOp(PlusPI, e1, _, _) | BinOp(MinusPI, e1, _, _) ->
+        begin
+          match (simplify_exp e1).enode with
+          | Lval _ | AddrOf _ as node -> {e with enode = node}
+          | _ -> raise (Explicit_pointer_address e1.eloc)
+        end
+      | _ -> e
+    in
+    HE.add cached_exp e res;
+    res
+
+module LvalOrRef = struct
+  type t = Lval of lval | Ref of lval
+
+  let pretty l =
+    let print f fmt x =
+      match x with
+      | Lval lv -> f fmt lv
+      | Ref lv -> Format.fprintf fmt "&%a" f lv
+    in
+    if Options.is_debug_key_enabled Options.DebugKeys.lvals
+    then print Cil_types_debug.pp_lval l
+    else print Printer.pp_lval l
+
+  let from_exp e =
+    let e = simplify_exp e in
+    match e.enode with
+      Lval lv -> Some (Lval lv)
+    | AddrOf lv -> Some (Ref lv)
+    | _ -> None
+
+  let is_pointer x =
+    match x with
+    | Ref _ -> true
+    | Lval lv ->
+      let t = Cil.typeOfLval lv in
+      match Cil.unrollType t with
+        TPtr _ | TArray _ -> true
+      | _ -> false
+end
+
+module Lval = struct
+  type t = lval
+
+  let simplify x = simplify_lval x
+
+  let compare = Cil_datatype.LvalStructEq.compare
+
+  let pretty l =
+    if Options.is_debug_key_enabled Options.DebugKeys.lvals
+    then Cil_types_debug.pp_lval l
+    else Printer.pp_lval l
+
+  let points_to lv = Mem (Cil.dummy_exp (Lval lv)), NoOffset
+end
+
+let decompose_lval lv1 : (lval * offset) list =
+  let rec list_of_offset (o: offset) : (offset*offset) list =
+    match o with
+      NoOffset -> [NoOffset,o]
+    | Index(e,ofs) ->
+      let li =
+        List.map
+          (fun (o1,o2) -> (Index(e,o1),o2))
+          (list_of_offset ofs)
+      in
+      (NoOffset,o)::li
+    | Field(f, ofs) ->
+      let li =
+        List.map
+          (fun (o1,o2) -> (Field(f,o1),o2))
+          (list_of_offset ofs)
+      in
+      (NoOffset,o)::li
+  in
+  let lv, off = Cil.removeOffsetLval lv1 in
+  List.map
+    (fun (o1,o2) -> Cil.addOffsetLval o1 lv, o2)
+    (list_of_offset off)
diff --git a/src/plugins/gui/gtk_compat.3.ml b/src/plugins/alias/simplified.mli
similarity index 63%
rename from src/plugins/gui/gtk_compat.3.ml
rename to src/plugins/alias/simplified.mli
index 98bab3686652a22a62db3c18d0eb7e00ec928da5..08f5e21c9e8d1785115db6de5160d856c54b7360 100644
--- a/src/plugins/gui/gtk_compat.3.ml
+++ b/src/plugins/alias/simplified.mli
@@ -20,28 +20,39 @@
 (*                                                                        *)
 (**************************************************************************)
 
-module Pango = struct
-  open Wutil_once
-
-  let small_font =
-    once (fun (f: GPango.font_description) ->
-        let f = f#copy in
-        let size = f#size - 2 in
-        f#modify ~size (); f)
-
-  let bold_font =
-    once (fun (f: GPango.font_description) ->
-        let f = f#copy in
-        let weight = `BOLD in
-        f#modify ~weight (); f)
-
-  let modify_font phi (widget: #GObj.widget) =
-    widget#misc#modify_font (phi widget#misc#pango_context#font_description)
-
-  let set_small_font w = modify_font small_font w
-  let set_bold_font w = modify_font bold_font w
+open Cil_types
+
+module LvalOrRef : sig
+  type t = Lval of lval | Ref of lval
+  val pretty : Format.formatter -> t -> unit
+
+  (* result stored in cache. May raise Explicit_pointer_address *)
+  val from_exp : exp -> t option
+
+  (* true if x is assimilable to a pointer type (explicit pointer or
+     memory adress or array *)
+  val is_pointer : t -> bool
+end
+
+(* exception raised when the program tries to access a memory location directly. *)
+exception Explicit_pointer_address of location
+
+module Lval : sig
+  type t = lval
+
+  val compare: t -> t -> int
+
+  (* result stored in cache. May raise Explicit_pointer_address *)
+  val simplify : lval -> lval
+
+  val pretty: Format.formatter -> t -> unit
+
+  (* (points_to x) = *x and (points_to &x) = x. Raise
+     Explicit_pointer_address when applied to BNone *)
+  val points_to : lval -> lval
 end
 
-let get_toolbar_index toolbar item = toolbar#get_item_index item#as_tool_item
+val decompose_lval : lval -> (lval * offset) list
 
-let window = GWindow.window
+(** clear the two caches *)
+val clear_cache : unit -> unit
diff --git a/src/plugins/alias/tests/basic/addrof.c b/src/plugins/alias/tests/basic/addrof.c
new file mode 100644
index 0000000000000000000000000000000000000000..838b4527950aea8619e4674e3e121b8d31439bd1
--- /dev/null
+++ b/src/plugins/alias/tests/basic/addrof.c
@@ -0,0 +1,11 @@
+int main () {
+  int **a, ***b, **y, *x, *z, p;
+  a = &x;
+  b = &y;
+  if (p)
+    y = &z;
+  else
+    *y = x;
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/assignment1.c b/src/plugins/alias/tests/basic/assignment1.c
new file mode 100644
index 0000000000000000000000000000000000000000..2851d98907fe53177b4139ba9868a78f6201cf74
--- /dev/null
+++ b/src/plugins/alias/tests/basic/assignment1.c
@@ -0,0 +1,11 @@
+// single pointer assignment
+// {a, b, c, d} are aliased
+
+int main () {
+
+  int *a=0, *b=0, *c=0, *d=0;
+  a = b;
+  b = c;
+  a = d;
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/assignment2.c b/src/plugins/alias/tests/basic/assignment2.c
new file mode 100644
index 0000000000000000000000000000000000000000..ba0a8dc53e64428a841d94466d52a9f6cfda563a
--- /dev/null
+++ b/src/plugins/alias/tests/basic/assignment2.c
@@ -0,0 +1,13 @@
+// double pointer assignment
+//  {a, c} are aliased
+//  {*a, *c, b, d} are aliased
+
+
+int main () {
+
+  int **a=0, *b=0, **c=0, *d=0;
+  *a = b;
+  *c = d;
+  a = c;
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/assignment3.c b/src/plugins/alias/tests/basic/assignment3.c
new file mode 100644
index 0000000000000000000000000000000000000000..203e93650c145bd0ee2a10cf547852a24551c02f
--- /dev/null
+++ b/src/plugins/alias/tests/basic/assignment3.c
@@ -0,0 +1,10 @@
+// address assignment
+// {a, c} are aliased
+
+int main () {
+
+  int *a=0, b=0, *c=0;
+  a = &b;
+  c = &b;
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/assignment4.c b/src/plugins/alias/tests/basic/assignment4.c
new file mode 100644
index 0000000000000000000000000000000000000000..136a763cb531aa5b7ac9db937a41a49d60ca5041
--- /dev/null
+++ b/src/plugins/alias/tests/basic/assignment4.c
@@ -0,0 +1,13 @@
+// double pointer assignment
+//  {a, c} are aliased
+//  {*a, *c, b, d} are aliased
+
+
+int main () {
+
+  int **a=0, *b=0, **c=0, *d=0;
+  *a = b;
+  *c = d;
+  b = d;
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/assignment5.c b/src/plugins/alias/tests/basic/assignment5.c
new file mode 100644
index 0000000000000000000000000000000000000000..03ccff7f6bf62d8eb127a9ff487c1b3bb0ecd6c4
--- /dev/null
+++ b/src/plugins/alias/tests/basic/assignment5.c
@@ -0,0 +1,12 @@
+// triple pointer assignment with some tricky alias
+//   {*a, b} are aliased
+//   {*(*a), *b, c, d} are aliased
+
+int main () {
+
+  int ***a=0, **b=0, *c=0, *d=0;
+  *a = b;
+  *b = c;
+  d = **a;
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/cast1.c b/src/plugins/alias/tests/basic/cast1.c
new file mode 100644
index 0000000000000000000000000000000000000000..4a0713d879d9ae2d319aba0c359a3d8f8dedc102
--- /dev/null
+++ b/src/plugins/alias/tests/basic/cast1.c
@@ -0,0 +1,14 @@
+// homogeneous cast
+//  {a, c} are aliased
+//  {b, d} are aliased
+
+
+int main () {
+
+  int *a=0, *b=0;
+  float *c=0, *d=0;
+  a = (int*) c;
+  d = (float*) b;
+  
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/conditional1.c b/src/plugins/alias/tests/basic/conditional1.c
new file mode 100644
index 0000000000000000000000000000000000000000..a668cd7d083a810096ccde023c6fa83985ad2105
--- /dev/null
+++ b/src/plugins/alias/tests/basic/conditional1.c
@@ -0,0 +1,15 @@
+// conditional cfg
+//  {a, b, c} are aliased
+
+int main () {
+
+  int *a=0, *b=0, *c=0;
+  if (a) {
+    a = b;
+  }
+  else {
+    a = c;
+  }
+  *a = 4;  
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/conditional2.c b/src/plugins/alias/tests/basic/conditional2.c
new file mode 100644
index 0000000000000000000000000000000000000000..7243bebdbde9675572b75eaa0c134bd65bd65fe1
--- /dev/null
+++ b/src/plugins/alias/tests/basic/conditional2.c
@@ -0,0 +1,20 @@
+// conditional cfg
+//  {*a, *b, c} are aliased
+//  {*(*a), *(*b), *c, d} are aliased
+//  {a, b} are aliased
+
+
+int main () {
+
+  int ***a, ***b, **c, *d, e;
+  b = &c;
+  c = &d;
+  d = &e;
+  if (a) {
+    a = b;
+  }
+  else {
+    a = &c;
+  }
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/conditional3.c b/src/plugins/alias/tests/basic/conditional3.c
new file mode 100644
index 0000000000000000000000000000000000000000..06d7dfbc131d38402a4ddbd96245cd579a4c1d44
--- /dev/null
+++ b/src/plugins/alias/tests/basic/conditional3.c
@@ -0,0 +1,26 @@
+// conditional with multiple levels of indirection
+//  {a, b, c} are aliased
+//  {*a, *b, *c, i, j} are aliased
+//  {*(*a), *(*b), *(*c), *i, *j, x, y} are aliased
+//  {*(*(*a)), *(*(*b)), *(*(*c)), *(*i), *(*j), *x, *y, t, u} are aliased
+
+
+
+int main () {
+  int ****a, ****b, ****c, ***i, ***j, **x, **y, *t, *u, p;
+  if (p) {
+    a=b;
+    b=&i;
+    i=&x;
+    x=&t;
+  }
+  else {
+    a=c;
+    c=&j;
+    j=&y;
+    y=&u;
+  }
+  p=0;
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/function1.c b/src/plugins/alias/tests/basic/function1.c
new file mode 100644
index 0000000000000000000000000000000000000000..63bc345a7f779fd9c10517e951607731a896436b
--- /dev/null
+++ b/src/plugins/alias/tests/basic/function1.c
@@ -0,0 +1,20 @@
+// function with no return
+//  {a, b} are aliased
+//  {c, d} are aliased
+
+
+void swap(int *x, int* y) {
+  int*z=0;
+  z=x;
+  x=y;
+  y=z;
+}
+
+
+int main(void)
+{
+  int *a=0, *b=0, *c=0, *d=0;
+  swap(a,b);
+  swap(c,d);
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/function2.c b/src/plugins/alias/tests/basic/function2.c
new file mode 100644
index 0000000000000000000000000000000000000000..e4411348cb39b56e76064ab07e3b5488281ed455
--- /dev/null
+++ b/src/plugins/alias/tests/basic/function2.c
@@ -0,0 +1,18 @@
+// malloc
+// no alias
+
+#include <stdlib.h>
+
+int* my_malloc(int size) {
+  int* res=0;
+  res = malloc(size);
+  return res;
+}
+
+int main(void)
+{
+  int *a=0, *b=0;
+  a=my_malloc(2);
+  b=my_malloc(3);
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/function3.c b/src/plugins/alias/tests/basic/function3.c
new file mode 100644
index 0000000000000000000000000000000000000000..2142dcd0adefbce2ee3397a11d0c13efbb286ae2
--- /dev/null
+++ b/src/plugins/alias/tests/basic/function3.c
@@ -0,0 +1,23 @@
+// function with a loop inside
+//  {a, b} are aliased
+//  {c, d} are aliased
+
+void *f1(int *x, int* y)
+{
+  int *tmp = x;
+
+  while (1) {
+    x=y;
+    y=tmp;
+    break;
+  }
+  return (void *) 0;
+}
+
+int main(void)
+{
+  int *a=0, *b=0, *c=0, *d=0;
+  f1(a,b);
+  f1(c,d);
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/function4.c b/src/plugins/alias/tests/basic/function4.c
new file mode 100644
index 0000000000000000000000000000000000000000..806b68cc3c364ead33143a0ad0a85e0cd9802a94
--- /dev/null
+++ b/src/plugins/alias/tests/basic/function4.c
@@ -0,0 +1,15 @@
+// funxtion with address agument
+//  {a, b} are aliased
+
+int * addr(int* x)
+{
+    return x;
+}
+
+int main(void)
+{
+  int *a=0, *b=0, c=0;
+  a = addr(&c);
+  b = &c;
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/function5.c b/src/plugins/alias/tests/basic/function5.c
new file mode 100644
index 0000000000000000000000000000000000000000..94247a286c146fc451f4f7107846146d9a43d995
--- /dev/null
+++ b/src/plugins/alias/tests/basic/function5.c
@@ -0,0 +1,19 @@
+// function with multiple returns
+//  {a, b, c} are aliased
+
+
+int * choice(int* x, int* y)
+{
+  int c=0;
+  if (c)
+    return x;
+  else
+    return y;
+}
+
+int main(void)
+{
+  int *a=0, *b=0, *c=0;
+  c = choice(a,b);
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/function6.c b/src/plugins/alias/tests/basic/function6.c
new file mode 100644
index 0000000000000000000000000000000000000000..416136692b9b58787dbd32ad55e216c24b5c4ad7
--- /dev/null
+++ b/src/plugins/alias/tests/basic/function6.c
@@ -0,0 +1,19 @@
+// function with no return
+// no alias
+
+
+void swap(int *x, int* y) {
+  int z=0;
+  z=*x;
+  *x=*y;
+  *y=z;
+}
+
+
+int main(void)
+{
+  int *a=0, *b=0, *c=0, *d=0;
+  swap(a,b);
+  swap(c,d);
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/globctr.c b/src/plugins/alias/tests/basic/globctr.c
new file mode 100644
index 0000000000000000000000000000000000000000..5b399b157aef468a2f7824d7cf13b636a4570036
--- /dev/null
+++ b/src/plugins/alias/tests/basic/globctr.c
@@ -0,0 +1,12 @@
+void f(int *x) {
+  int y = 0;
+  *x = y;
+}
+
+int main(void)
+{
+  int *a=0, *b=0;
+  f(a);
+  f(b);
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/loop.c b/src/plugins/alias/tests/basic/loop.c
new file mode 100644
index 0000000000000000000000000000000000000000..1b8f58d53345c679b86556995b74d7b37bdd9ea1
--- /dev/null
+++ b/src/plugins/alias/tests/basic/loop.c
@@ -0,0 +1,15 @@
+// used to lead to a loop in the graph - fixed
+// no alias since there is an infinite loop
+
+int main()
+{
+  while (1) {
+    int l[1] = {0};
+    int *n_0 = & l[1];
+    n_0 = & l[1] + 0;
+    int w = 0;
+    if (w)
+      l[0] = *(& l[1] + 0);
+  }
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/oracle/addrof.res.oracle b/src/plugins/alias/tests/basic/oracle/addrof.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..8b2b579be28d8eee2dbeedad41454f7dcba4fbe9
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/addrof.res.oracle
@@ -0,0 +1,15 @@
+[kernel] Parsing addrof.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: a = & x;
+[alias] May-aliases after instruction  a = & x;  are  {*a, x}
+[alias] analysing instruction: b = & y;
+[alias] May-aliases after instruction  b = & y;  are  {*a, x}  {*b, y}
+[alias] analysing instruction: y = & z;
+[alias] May-aliases after instruction  y = & z;  are
+  {*a, x}  {*b, y}  {*(*b), *y, z}
+[alias] analysing instruction: *y = x;
+[alias] May-aliases after instruction  *y = x;  are  {*(*b), *a, *y, x}  {*b, a, y}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are
+  {*b, a, y}  {*(*b), *a, *y, x, z}
+[alias] May-aliases at the end of function main: {*b, a, y}  {*(*b), *a, *y, x, z}
diff --git a/src/plugins/alias/tests/basic/oracle/assignment1.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..3c262c6c2ce8463df14d5cf6c6d31fadae384515
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/assignment1.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing assignment1.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: a = b;
+[alias] May-aliases after instruction  a = b;  are  {a, b}
+[alias] analysing instruction: b = c;
+[alias] May-aliases after instruction  b = c;  are  {a, b, c}
+[alias] analysing instruction: a = d;
+[alias] May-aliases after instruction  a = d;  are  {a, b, c, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b, c, d}
+[alias] May-aliases at the end of function main: {a, b, c, d}
diff --git a/src/plugins/alias/tests/basic/oracle/assignment2.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..0ad4f006ba3b3cf35f8fae1b61a40345b12f4143
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/assignment2.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing assignment2.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int **a = (int **)0;
+[alias] May-aliases after instruction  int **a = (int **)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int **c = (int **)0;
+[alias] May-aliases after instruction  int **c = (int **)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: *a = b;
+[alias] May-aliases after instruction  *a = b;  are  {*a, b}
+[alias] analysing instruction: *c = d;
+[alias] May-aliases after instruction  *c = d;  are  {*a, b}  {*c, d}
+[alias] analysing instruction: a = c;
+[alias] May-aliases after instruction  a = c;  are  {a, c}  {*a, *c, b, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, c}  {*a, *c, b, d}
+[alias] May-aliases at the end of function main: {a, c}  {*a, *c, b, d}
diff --git a/src/plugins/alias/tests/basic/oracle/assignment3.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment3.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..65a7c76ee2a2b772a961b9574d747983a02c03a3
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/assignment3.res.oracle
@@ -0,0 +1,15 @@
+[kernel] Parsing assignment3.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int b = 0;
+[alias] May-aliases after instruction  int b = 0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: a = & b;
+[alias] May-aliases after instruction  a = & b;  are  <none>
+[alias] analysing instruction: c = & b;
+[alias] May-aliases after instruction  c = & b;  are  {a, c}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, c}
+[alias] May-aliases at the end of function main: {a, c}
diff --git a/src/plugins/alias/tests/basic/oracle/assignment4.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment4.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..c422587f1a0662ac753d85d13b48ce30d9779b0d
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/assignment4.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing assignment4.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int **a = (int **)0;
+[alias] May-aliases after instruction  int **a = (int **)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int **c = (int **)0;
+[alias] May-aliases after instruction  int **c = (int **)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: *a = b;
+[alias] May-aliases after instruction  *a = b;  are  {*a, b}
+[alias] analysing instruction: *c = d;
+[alias] May-aliases after instruction  *c = d;  are  {*a, b}  {*c, d}
+[alias] analysing instruction: b = d;
+[alias] May-aliases after instruction  b = d;  are  {a, c}  {*a, *c, b, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, c}  {*a, *c, b, d}
+[alias] May-aliases at the end of function main: {a, c}  {*a, *c, b, d}
diff --git a/src/plugins/alias/tests/basic/oracle/assignment5.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment5.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..fc9d35993fc2fd1d3228b9f1888ccc80efc11155
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/assignment5.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing assignment5.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int ***a = (int ***)0;
+[alias] May-aliases after instruction  int ***a = (int ***)0;  are  <none>
+[alias] analysing instruction: int **b = (int **)0;
+[alias] May-aliases after instruction  int **b = (int **)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: *a = b;
+[alias] May-aliases after instruction  *a = b;  are  {*a, b}
+[alias] analysing instruction: *b = c;
+[alias] May-aliases after instruction  *b = c;  are  {*a, b}  {*(*a), *b, c}
+[alias] analysing instruction: d = *(*a);
+[alias] May-aliases after instruction  d = *(*a);  are  {*a, b}  {*(*a), *b, c, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {*a, b}  {*(*a), *b, c, d}
+[alias] May-aliases at the end of function main: {*a, b}  {*(*a), *b, c, d}
diff --git a/src/plugins/alias/tests/basic/oracle/cast1.res.oracle b/src/plugins/alias/tests/basic/oracle/cast1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..efb26a239fe217242d96a035e5f532512856f69e
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/cast1.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing cast1.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: float *c = (float *)0;
+[alias] May-aliases after instruction  float *c = (float *)0;  are  <none>
+[alias] analysing instruction: float *d = (float *)0;
+[alias] May-aliases after instruction  float *d = (float *)0;  are  <none>
+[alias] analysing instruction: a = (int *)c;
+[alias:unsafe-cast] cast1.c:10: Warning: unsafe cast from float * to int *
+[alias] May-aliases after instruction  a = (int *)c;  are  {a, c}
+[alias] analysing instruction: d = (float *)b;
+[alias:unsafe-cast] cast1.c:11: Warning: unsafe cast from int * to float *
+[alias] May-aliases after instruction  d = (float *)b;  are  {a, c}  {b, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, c}  {b, d}
+[alias] May-aliases at the end of function main: {a, c}  {b, d}
diff --git a/src/plugins/alias/tests/basic/oracle/conditional1.res.oracle b/src/plugins/alias/tests/basic/oracle/conditional1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..c903b74f5fe55bbca3300a508bb311813cbdd43c
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/conditional1.res.oracle
@@ -0,0 +1,17 @@
+[kernel] Parsing conditional1.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: a = b;
+[alias] May-aliases after instruction  a = b;  are  {a, b}
+[alias] analysing instruction: a = c;
+[alias] May-aliases after instruction  a = c;  are  {a, c}
+[alias] analysing instruction: *a = 4;
+[alias] May-aliases after instruction  *a = 4;  are  {a, b, c}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b, c}
+[alias] May-aliases at the end of function main: {a, b, c}
diff --git a/src/plugins/alias/tests/basic/oracle/conditional2.res.oracle b/src/plugins/alias/tests/basic/oracle/conditional2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..6088f9fb04df624989e4038e8fc723c7f40e880e
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/conditional2.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing conditional2.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: b = & c;
+[alias] May-aliases after instruction  b = & c;  are  {*b, c}
+[alias] analysing instruction: c = & d;
+[alias] May-aliases after instruction  c = & d;  are  {*b, c}  {*(*b), *c, d}
+[alias] analysing instruction: d = & e;
+[alias] May-aliases after instruction  d = & e;  are  {*b, c}  {*(*b), *c, d}
+[alias] analysing instruction: a = b;
+[alias] May-aliases after instruction  a = b;  are
+  {*a, *b, c}  {*(*a), *(*b), *c, d}  {a, b}
+[alias] analysing instruction: a = & c;
+[alias] May-aliases after instruction  a = & c;  are
+  {*a, *b, c}  {*(*a), *(*b), *c, d}  {a, b}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are
+  {*a, *b, c}  {*(*a), *(*b), *c, d}  {a, b}
+[alias] May-aliases at the end of function main:
+  {*a, *b, c}  {*(*a), *(*b), *c, d}  {a, b}
diff --git a/src/plugins/alias/tests/basic/oracle/conditional3.res.oracle b/src/plugins/alias/tests/basic/oracle/conditional3.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..19088629ddb2ab448d832017d538ed52f23d0a08
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/conditional3.res.oracle
@@ -0,0 +1,35 @@
+[kernel] Parsing conditional3.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: a = b;
+[alias] May-aliases after instruction  a = b;  are  {a, b}
+[alias] analysing instruction: b = & i;
+[alias] May-aliases after instruction  b = & i;  are  {a, b}  {*a, *b, i}
+[alias] analysing instruction: i = & x;
+[alias] May-aliases after instruction  i = & x;  are
+  {a, b}  {*a, *b, i}  {*(*a), *(*b), *i, x}
+[alias] analysing instruction: x = & t;
+[alias] May-aliases after instruction  x = & t;  are
+  {a, b}  {*a, *b, i}  {*(*a), *(*b), *i, x}
+  {*(*(*a)), *(*(*b)), *(*i), *x, t}
+[alias] analysing instruction: a = c;
+[alias] May-aliases after instruction  a = c;  are  {a, c}
+[alias] analysing instruction: c = & j;
+[alias] May-aliases after instruction  c = & j;  are  {a, c}  {*a, *c, j}
+[alias] analysing instruction: j = & y;
+[alias] May-aliases after instruction  j = & y;  are
+  {a, c}  {*a, *c, j}  {*(*a), *(*c), *j, y}
+[alias] analysing instruction: y = & u;
+[alias] May-aliases after instruction  y = & u;  are
+  {a, c}  {*a, *c, j}  {*(*a), *(*c), *j, y}
+  {*(*(*a)), *(*(*c)), *(*j), *y, u}
+[alias] analysing instruction: p = 0;
+[alias] May-aliases after instruction  p = 0;  are
+  {a, b, c}  {*a, *b, *c, i, j}  {*(*a), *(*b), *(*c), *i, *j, x, y}
+  {*(*(*a)), *(*(*b)), *(*(*c)), *(*i), *(*j), *x, *y, t, u}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are
+  {a, b, c}  {*a, *b, *c, i, j}  {*(*a), *(*b), *(*c), *i, *j, x, y}
+  {*(*(*a)), *(*(*b)), *(*(*c)), *(*i), *(*j), *x, *y, t, u}
+[alias] May-aliases at the end of function main:
+  {a, b, c}  {*a, *b, *c, i, j}  {*(*a), *(*b), *(*c), *i, *j, x, y}
+  {*(*(*a)), *(*(*b)), *(*(*c)), *(*i), *(*j), *x, *y, t, u}
diff --git a/src/plugins/alias/tests/basic/oracle/function1.res.oracle b/src/plugins/alias/tests/basic/oracle/function1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..a22d297fdc0acd740dd01e992ac832c4051e6257
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/function1.res.oracle
@@ -0,0 +1,31 @@
+[kernel] Parsing function1.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: swap(a,b);
+[alias] analysing function: swap
+[alias] analysing instruction: int *z = (int *)0;
+[alias] May-aliases after instruction  int *z = (int *)0;  are  <none>
+[alias] analysing instruction: z = x;
+[alias] May-aliases after instruction  z = x;  are  {x, z}
+[alias] analysing instruction: x = y;
+[alias] May-aliases after instruction  x = y;  are  {x, y, z}
+[alias] analysing instruction: y = z;
+[alias] May-aliases after instruction  y = z;  are  {x, y, z}
+[alias] May-aliases at the end of function swap: {x, y, z}
+[alias] May-aliases after instruction  swap(a,b);  are  {a, b}
+[alias] analysing instruction: swap(c,d);
+[alias] May-aliases after instruction  swap(c,d);  are  {a, b}  {c, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b}  {c, d}
+[alias] May-aliases at the end of function main: {a, b}  {c, d}
+[alias] analysing function: swap
+[alias] analysing instruction: int *z = (int *)0;
+[alias] May-aliases after instruction  int *z = (int *)0;  are  <none>
+[alias] May-aliases at the end of function swap: {x, y, z}
diff --git a/src/plugins/alias/tests/basic/oracle/function2.res.oracle b/src/plugins/alias/tests/basic/oracle/function2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..1e4decb3e431ddaeca4ca82775f8bc469b5f9756
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/function2.res.oracle
@@ -0,0 +1,136 @@
+[kernel] Parsing function2.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: a = my_malloc(2);
+[alias] analysing function: my_malloc
+[alias] analysing instruction: int *res = (int *)0;
+[alias] May-aliases after instruction  int *res = (int *)0;  are  <none>
+[alias] analysing instruction: res = (int *)malloc((size_t)size);
+[alias] May-aliases after instruction  res = (int *)malloc((size_t)size);  are
+  <none>
+[alias] May-aliases at the end of function my_malloc: <none>
+[alias] May-aliases after instruction  a = my_malloc(2);  are  <none>
+[alias] analysing instruction: b = my_malloc(3);
+[alias] May-aliases after instruction  b = my_malloc(3);  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: my_malloc
+[alias] analysing instruction: int *res = (int *)0;
+[alias] May-aliases after instruction  int *res = (int *)0;  are  <none>
+[alias] May-aliases at the end of function my_malloc: <none>
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/basic/oracle/function3.res.oracle b/src/plugins/alias/tests/basic/oracle/function3.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..d32eba5759924636897ce753d362cec982b56a90
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/function3.res.oracle
@@ -0,0 +1,27 @@
+[kernel] Parsing function3.c (with preprocessing)
+[alias] analysing function: f1
+[alias] analysing instruction: int *tmp = x;
+[alias] May-aliases after instruction  int *tmp = x;  are  {x, tmp}
+[alias] analysing instruction: x = y;
+[alias] May-aliases after instruction  x = y;  are  {x, y, tmp}
+[alias] analysing instruction: y = tmp;
+[alias] May-aliases after instruction  y = tmp;  are  {x, y, tmp}
+[alias] analysing instruction: __retres = (void *)0;
+[alias] May-aliases after instruction  __retres = (void *)0;  are  {x, y, tmp}
+[alias] May-aliases at the end of function f1: {x, y, tmp}
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: f1(a,b);
+[alias] May-aliases after instruction  f1(a,b);  are  {a, b}
+[alias] analysing instruction: f1(c,d);
+[alias] May-aliases after instruction  f1(c,d);  are  {a, b}  {c, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b}  {c, d}
+[alias] May-aliases at the end of function main: {a, b}  {c, d}
diff --git a/src/plugins/alias/tests/basic/oracle/function4.res.oracle b/src/plugins/alias/tests/basic/oracle/function4.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..b7e6c7adde41156fd688fe72ca19bc4252f34c0d
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/function4.res.oracle
@@ -0,0 +1,17 @@
+[kernel] Parsing function4.c (with preprocessing)
+[alias] analysing function: addr
+[alias] May-aliases at the end of function addr: <none>
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int c = 0;
+[alias] May-aliases after instruction  int c = 0;  are  <none>
+[alias] analysing instruction: a = addr(& c);
+[alias] May-aliases after instruction  a = addr(& c);  are  <none>
+[alias] analysing instruction: b = & c;
+[alias] May-aliases after instruction  b = & c;  are  {a, b}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b}
+[alias] May-aliases at the end of function main: {a, b}
diff --git a/src/plugins/alias/tests/basic/oracle/function5.res.oracle b/src/plugins/alias/tests/basic/oracle/function5.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..300762d6f2d441f3222d3ca79dcda3f7e0b4fd0d
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/function5.res.oracle
@@ -0,0 +1,21 @@
+[kernel] Parsing function5.c (with preprocessing)
+[alias] analysing function: choice
+[alias] analysing instruction: int c = 0;
+[alias] May-aliases after instruction  int c = 0;  are  <none>
+[alias] analysing instruction: __retres = x;
+[alias] May-aliases after instruction  __retres = x;  are  {x, __retres}
+[alias] analysing instruction: __retres = y;
+[alias] May-aliases after instruction  __retres = y;  are  {y, __retres}
+[alias] May-aliases at the end of function choice: {x, y, __retres}
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: c = choice(a,b);
+[alias] May-aliases after instruction  c = choice(a,b);  are  {a, b, c}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b, c}
+[alias] May-aliases at the end of function main: {a, b, c}
diff --git a/src/plugins/alias/tests/basic/oracle/function6.res.oracle b/src/plugins/alias/tests/basic/oracle/function6.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..4d8f8fa4a01fce5e95e6b5afdc4c4f24aec1c045
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/function6.res.oracle
@@ -0,0 +1,31 @@
+[kernel] Parsing function6.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: swap(a,b);
+[alias] analysing function: swap
+[alias] analysing instruction: int z = 0;
+[alias] May-aliases after instruction  int z = 0;  are  <none>
+[alias] analysing instruction: z = *x;
+[alias] May-aliases after instruction  z = *x;  are  <none>
+[alias] analysing instruction: *x = *y;
+[alias] May-aliases after instruction  *x = *y;  are  <none>
+[alias] analysing instruction: *y = z;
+[alias] May-aliases after instruction  *y = z;  are  <none>
+[alias] May-aliases at the end of function swap: <none>
+[alias] May-aliases after instruction  swap(a,b);  are  <none>
+[alias] analysing instruction: swap(c,d);
+[alias] May-aliases after instruction  swap(c,d);  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
+[alias] analysing function: swap
+[alias] analysing instruction: int z = 0;
+[alias] May-aliases after instruction  int z = 0;  are  <none>
+[alias] May-aliases at the end of function swap: <none>
diff --git a/src/plugins/alias/tests/basic/oracle/globctr.res.oracle b/src/plugins/alias/tests/basic/oracle/globctr.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..64f2826db29bf339219770a5cf558ec4f579b092
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/globctr.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing globctr.c (with preprocessing)
+[alias] analysing function: f
+[alias] analysing instruction: int y = 0;
+[alias] May-aliases after instruction  int y = 0;  are  <none>
+[alias] analysing instruction: *x = y;
+[alias] May-aliases after instruction  *x = y;  are  <none>
+[alias] May-aliases at the end of function f: <none>
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: f(a);
+[alias] May-aliases after instruction  f(a);  are  <none>
+[alias] analysing instruction: f(b);
+[alias] May-aliases after instruction  f(b);  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/basic/oracle/loop.res.oracle b/src/plugins/alias/tests/basic/oracle/loop.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..9ef827f6daf8c1920926e31460dc19ab04c72bac
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/loop.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing loop.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int l[1] = {0};
+[alias] May-aliases after instruction  int l[1] = {0};  are  <none>
+[alias] analysing instruction: int *n_0 = & l[1];
+[alias] May-aliases after instruction  int *n_0 = & l[1];  are  <none>
+[alias] analysing instruction: n_0 = & l[1] + 0;
+[alias] May-aliases after instruction  n_0 = & l[1] + 0;  are  <none>
+[alias] analysing instruction: int w = 0;
+[alias] May-aliases after instruction  int w = 0;  are  <none>
+[alias] analysing instruction: l[0] = *(& l[1] + 0);
+[alias] May-aliases after instruction  l[0] = *(& l[1] + 0);  are  <none>
+[alias] analysing instruction: int l[1] = {0};
+[alias] May-aliases after instruction  int l[1] = {0};  are  <none>
+[alias] analysing instruction: int *n_0 = & l[1];
+[alias] May-aliases after instruction  int *n_0 = & l[1];  are  <none>
+[alias:no-return] loop.c:4: Warning: 
+  function main does not return; analysis may be unsound
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/basic/oracle/steensgaard.res.oracle b/src/plugins/alias/tests/basic/oracle/steensgaard.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..7b9c15f79cba40c1eb3120b93a10733bee758d1e
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/steensgaard.res.oracle
@@ -0,0 +1,17 @@
+[kernel] Parsing steensgaard.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: a = & x;
+[alias] May-aliases after instruction  a = & x;  are  <none>
+[alias] analysing instruction: b = & y;
+[alias] May-aliases after instruction  b = & y;  are  {*b, y}
+[alias] analysing instruction: y = & z;
+[alias] May-aliases after instruction  y = & z;  are  {*b, y}
+[alias] analysing instruction: y = & x;
+[alias] May-aliases after instruction  y = & x;  are  {*b, a, y}
+[alias] analysing instruction: c = & y;
+[alias] May-aliases after instruction  c = & y;  are  {*b, *c, a, y}  {b, c}
+[alias] analysing instruction: *y = 4;
+[alias] May-aliases after instruction  *y = 4;  are  {*b, *c, a, y}  {b, c}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {*b, *c, a, y}  {b, c}
+[alias] May-aliases at the end of function main: {*b, *c, a, y}  {b, c}
diff --git a/src/plugins/alias/tests/basic/oracle/switch1.res.oracle b/src/plugins/alias/tests/basic/oracle/switch1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..0819df147033b71a430fa6c56a9b42583ed83fa6
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/switch1.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing switch1.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: int e = 0;
+[alias] May-aliases after instruction  int e = 0;  are  <none>
+[alias] analysing instruction: case 1: a = d;
+[alias] May-aliases after instruction  case 1: a = d;  are  {a, d}
+[alias] analysing instruction: case 2: b = d;
+[alias] May-aliases after instruction  case 2: b = d;  are  {b, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b, d}
+[alias] May-aliases at the end of function main: {a, b, d}
diff --git a/src/plugins/alias/tests/basic/oracle/switch2.res.oracle b/src/plugins/alias/tests/basic/oracle/switch2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..40e0e801215e67cf06dfbc103ea1341b897bd96a
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/switch2.res.oracle
@@ -0,0 +1,21 @@
+[kernel] Parsing switch2.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: int e = 0;
+[alias] May-aliases after instruction  int e = 0;  are  <none>
+[alias] analysing instruction: case 1: a = d;
+[alias] May-aliases after instruction  case 1: a = d;  are  {a, d}
+[alias] analysing instruction: case 2: b = d;
+[alias] May-aliases after instruction  case 2: b = d;  are  {b, d}
+[alias] analysing instruction: default: c = d;
+[alias] May-aliases after instruction  default: c = d;  are  {c, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b, c, d}
+[alias] May-aliases at the end of function main: {a, b, c, d}
diff --git a/src/plugins/alias/tests/basic/oracle/while_for1.res.oracle b/src/plugins/alias/tests/basic/oracle/while_for1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..228274eef6fbd1b252d69ecb7bf0cf0c763c528e
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/while_for1.res.oracle
@@ -0,0 +1,127 @@
+[kernel] Parsing while_for1.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: int *s = (int *)0;
+[alias] May-aliases after instruction  int *s = (int *)0;  are  <none>
+[alias] analysing instruction: int idx = 0;
+[alias] May-aliases after instruction  int idx = 0;  are  <none>
+[alias] analysing instruction: s = (int *)malloc((size_t)idx);
+[alias] May-aliases after instruction  s = (int *)malloc((size_t)idx);  are  <none>
+[alias] analysing instruction: idx ++;
+[alias] May-aliases after instruction  idx ++;  are  <none>
+[alias] analysing instruction: s = (int *)malloc((size_t)idx);
+[alias] May-aliases after instruction  s = (int *)malloc((size_t)idx);  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/basic/oracle/while_for2.res.oracle b/src/plugins/alias/tests/basic/oracle/while_for2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..3986565e550a94827f115749244cece16be1b6ce
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/while_for2.res.oracle
@@ -0,0 +1,13 @@
+[kernel] Parsing while_for2.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: a = b;
+[alias] May-aliases after instruction  a = b;  are  {a, b}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b}
+[alias] May-aliases at the end of function main: {a, b}
diff --git a/src/plugins/alias/tests/basic/oracle/while_for3.res.oracle b/src/plugins/alias/tests/basic/oracle/while_for3.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..382069e577e43db211419f390f12de9f17a9da35
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/while_for3.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing while_for3.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: int i = 0;
+[alias] May-aliases after instruction  int i = 0;  are  <none>
+[alias] analysing instruction: a = b;
+[alias] May-aliases after instruction  a = b;  are  {a, b}
+[alias] analysing instruction: __Cont: i ++;
+[alias] May-aliases after instruction  __Cont: i ++;  are  {a, b}
+[alias] analysing instruction: a = b;
+[alias] May-aliases after instruction  a = b;  are  {a, b}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b}
+[alias] May-aliases at the end of function main: {a, b}
diff --git a/src/plugins/alias/tests/basic/steensgaard.c b/src/plugins/alias/tests/basic/steensgaard.c
new file mode 100644
index 0000000000000000000000000000000000000000..7afb87e247941e9aa1206c86324763ac77867c17
--- /dev/null
+++ b/src/plugins/alias/tests/basic/steensgaard.c
@@ -0,0 +1,19 @@
+// from steensgaard's paper
+//  {*b, *c, a, y} are aliased
+//  {b, c} are aliased
+
+
+int main () {
+  int *a, **b, **c, *y, x, z, p;
+  a = &x;
+  b = &y;
+  if (p)
+    y = &z;
+  else
+    y = &x;
+  c = &y;
+  *y = 4;
+  return 0;
+}
+
+
diff --git a/src/plugins/alias/tests/basic/switch1.c b/src/plugins/alias/tests/basic/switch1.c
new file mode 100644
index 0000000000000000000000000000000000000000..c0b97a18180983bda26f3439f939f604cc58624d
--- /dev/null
+++ b/src/plugins/alias/tests/basic/switch1.c
@@ -0,0 +1,17 @@
+// switch
+//  {a, b, d} are aliased
+
+int main ()
+{
+  int *a=0, *b=0, *c=0, *d=0, e=0;
+  switch (e) {
+  case 1:
+    a=d;
+    break;
+  case 2:
+    b=d;
+    break;
+  }
+    
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/switch2.c b/src/plugins/alias/tests/basic/switch2.c
new file mode 100644
index 0000000000000000000000000000000000000000..05d162bd67a0dd14fb8010af75281c989425e705
--- /dev/null
+++ b/src/plugins/alias/tests/basic/switch2.c
@@ -0,0 +1,19 @@
+// switch with default
+//  {a, b, c, d} are aliased
+
+int main ()
+{
+  int *a=0, *b=0, *c=0, *d=0, e=0;
+  switch (e) {
+  case 1:
+    a=d;
+    break;
+  case 2:
+    b=d;
+    break;
+  default:
+    c=d;
+  }
+    
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/while_for1.c b/src/plugins/alias/tests/basic/while_for1.c
new file mode 100644
index 0000000000000000000000000000000000000000..06ef79f5f89d2573152cf3035a59fa55d2e8baad
--- /dev/null
+++ b/src/plugins/alias/tests/basic/while_for1.c
@@ -0,0 +1,13 @@
+// for loop
+// no alias
+
+#include <stdlib.h>
+
+int main ()
+{
+  int* s = 0;
+  for (int idx = 0; idx < 10; idx++) {
+    s = malloc(idx);
+  }
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/while_for2.c b/src/plugins/alias/tests/basic/while_for2.c
new file mode 100644
index 0000000000000000000000000000000000000000..f98677716b7e80a6f746b6e7033a61c4069b4c7f
--- /dev/null
+++ b/src/plugins/alias/tests/basic/while_for2.c
@@ -0,0 +1,17 @@
+// while loops with trivial conditions
+//  {a, b} are aliased
+
+int main ()
+{
+  int *a=0, *b=0, *c=0;
+  while (1) {
+    a = b;
+    break;
+  }
+
+   while (0) {
+    a = c;
+    break;
+  }
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/while_for3.c b/src/plugins/alias/tests/basic/while_for3.c
new file mode 100644
index 0000000000000000000000000000000000000000..e7ffb9f39523ca14abdc8ba00b84fd55699e195b
--- /dev/null
+++ b/src/plugins/alias/tests/basic/while_for3.c
@@ -0,0 +1,16 @@
+// continue
+//  {a, b} are aliased
+
+int main ()
+{
+  int *a=0, *b=0, *c=0;
+  for (int i=0; i<10 ;i++) {
+    if (1) {
+      a = b;
+      continue;
+    }
+    a = c;
+  }
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/fixed_bugs/empty_nodes.c b/src/plugins/alias/tests/fixed_bugs/empty_nodes.c
new file mode 100644
index 0000000000000000000000000000000000000000..004a207da7443ec4a3ee2c1c21913e53641ccd0b
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/empty_nodes.c
@@ -0,0 +1,12 @@
+void f(char **x, char **y, char **z)
+{
+  char *t;
+  *y = t + (*y - *x);
+  *z = t + (*z - *x);
+  *x = t;
+}
+
+void g(char **a)
+{
+  f(a,a,a);
+}
diff --git a/src/plugins/alias/tests/fixed_bugs/gzip124.c b/src/plugins/alias/tests/fixed_bugs/gzip124.c
new file mode 100644
index 0000000000000000000000000000000000000000..70a9cc2955966f21c8ea856531bf467464e66355
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/gzip124.c
@@ -0,0 +1,12 @@
+int main(void)
+{
+  int __retres;
+  short prev[1];
+  short *p;
+  short tmp_0 = (short)0;
+  *(& prev[1] + 0) = tmp_0;
+  prev[0] = (short)0;
+  if (0 + 0) p = & prev[1] + (int)*p; else p = & prev[*p];
+  __retres = 0;
+  return __retres;
+}
diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/empty_nodes.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/empty_nodes.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..970b25bd3ea518640e4cdca331963fd23ab641f8
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/oracle/empty_nodes.res.oracle
@@ -0,0 +1,13 @@
+[kernel] Parsing empty_nodes.c (with preprocessing)
+[alias] analysing function: f
+[alias] analysing instruction: *y = t + (*y - *x);
+[alias] May-aliases after instruction  *y = t + (*y - *x);  are  {*y, t}
+[alias] analysing instruction: *z = t + (*z - *x);
+[alias] May-aliases after instruction  *z = t + (*z - *x);  are  {*y, *z, t}  {y, z}
+[alias] analysing instruction: *x = t;
+[alias] May-aliases after instruction  *x = t;  are  {*x, *y, *z, t}  {x, y, z}
+[alias] May-aliases at the end of function f: {*x, *y, *z, t}  {x, y, z}
+[alias] analysing function: g
+[alias] analysing instruction: f(a,a,a);
+[alias] May-aliases after instruction  f(a,a,a);  are  <none>
+[alias] May-aliases at the end of function g: <none>
diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/gzip124.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/gzip124.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..fd9878fef65bf1ea35de5b51eef9ccfe7b40d5a0
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/oracle/gzip124.res.oracle
@@ -0,0 +1,15 @@
+[kernel] Parsing gzip124.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: short tmp_0 = (short)0;
+[alias] May-aliases after instruction  short tmp_0 = (short)0;  are  <none>
+[alias] analysing instruction: *(& prev[1] + 0) = tmp_0;
+[alias] May-aliases after instruction  *(& prev[1] + 0) = tmp_0;  are  <none>
+[alias] analysing instruction: prev[0] = (short)0;
+[alias] May-aliases after instruction  prev[0] = (short)0;  are  <none>
+[alias] analysing instruction: p = & prev[1] + (int)*p;
+[alias] May-aliases after instruction  p = & prev[1] + (int)*p;  are  <none>
+[alias] analysing instruction: p = & prev[*p];
+[alias] May-aliases after instruction  p = & prev[*p];  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/semver.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/semver.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..bdc3f9de65441a71704fe3c6c2faf4b5d51f684b
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/oracle/semver.res.oracle
@@ -0,0 +1,12 @@
+[kernel] Parsing semver.c (with preprocessing)
+[alias] analysing function: f
+[alias] May-aliases at the end of function f: <none>
+[alias] analysing function: main
+[alias] analysing instruction: f((int *)*("1" + 2));
+[alias:unsafe-cast] semver.c:6: Warning: unsafe cast from char to int *
+[alias:unsupported:addr] semver.c:6: Warning: 
+  unsupported feature: explicit pointer address: (int *)*("1" + 2); analysis may be unsound
+[alias] May-aliases after instruction  f((int *)*("1" + 2));  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/tkn-2.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/tkn-2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..7843cab155742b5e87b1d4e3c6fd67107fca9412
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/oracle/tkn-2.res.oracle
@@ -0,0 +1,9 @@
+[kernel] Parsing tkn-2.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: a = (int *)(& a);
+[alias:unsafe-cast] tkn-2.c:6: Warning: unsafe cast from int ** to int *
+[alias] tkn-2.c:6: Warning: ignoring assignment of the form: a = (int *)(& a)
+[alias] May-aliases after instruction  a = (int *)(& a);  are  <none>
+[alias] analysing instruction: __retres = *a;
+[alias] May-aliases after instruction  __retres = *a;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/union_vmap.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/union_vmap.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..606169550d1d780734a260fb8b0af502e57a26c5
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/oracle/union_vmap.res.oracle
@@ -0,0 +1,21 @@
+[kernel] Parsing union_vmap.c (with preprocessing)
+[alias] analysing function: CPS_ParseKey
+[alias] analysing instruction: char *s2 = CPS_SplitWord((char *)"a");
+[alias] analysing function: CPS_SplitWord
+[alias] May-aliases at the end of function CPS_SplitWord: <none>
+[alias:unsafe-cast] union_vmap.c:11: Warning: 
+  unsafe cast from char const * to char *
+[alias] May-aliases after instruction  char *s2 = CPS_SplitWord((char *)"a");  are
+  <none>
+[alias] analysing instruction: char *s3 = CPS_SplitWord((char *)"b");
+[alias:unsafe-cast] union_vmap.c:12: Warning: 
+  unsafe cast from char const * to char *
+[alias] May-aliases after instruction  char *s3 = CPS_SplitWord((char *)"b");  are
+  <none>
+[alias] analysing instruction: *key = s3;
+[alias] May-aliases after instruction  *key = s3;  are  {*key, s3}
+[alias] analysing instruction: *key = s2;
+[alias] May-aliases after instruction  *key = s2;  are  {*key, s2}
+[alias] May-aliases at the end of function CPS_ParseKey: {*key, s2, s3}
+[alias] analysing function: CPS_SplitWord
+[alias] May-aliases at the end of function CPS_SplitWord: <none>
diff --git a/src/plugins/alias/tests/fixed_bugs/semver.c b/src/plugins/alias/tests/fixed_bugs/semver.c
new file mode 100644
index 0000000000000000000000000000000000000000..d93edc0b90eb1d95415b0dd17453a639414a8d4e
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/semver.c
@@ -0,0 +1,8 @@
+void f (int* x) {
+}
+
+int main(void)
+{
+	f ((int*)*("1" + 2));
+	return 0;
+}
diff --git a/src/plugins/alias/tests/fixed_bugs/tkn-2.c b/src/plugins/alias/tests/fixed_bugs/tkn-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..97ee64b4f9aa53e56ec9766877bad8dae52f260e
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/tkn-2.c
@@ -0,0 +1,8 @@
+// leads to a loop; taken from open-source-case-studies/cerberus
+
+int main()
+{
+  int* a;
+  a = (int*)(& a);
+  return *a;
+}
diff --git a/src/plugins/alias/tests/fixed_bugs/union_vmap.c b/src/plugins/alias/tests/fixed_bugs/union_vmap.c
new file mode 100644
index 0000000000000000000000000000000000000000..5bf04ceddf9510e34cf3465710a71896ed841990
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/union_vmap.c
@@ -0,0 +1,21 @@
+// from open-source-case-studies/chrony
+
+char* CPS_SplitWord(char *line)
+{
+  return line;
+}
+
+void CPS_ParseKey()
+{
+	char **key;
+  char *s2 = CPS_SplitWord("a");
+  char *s3 = CPS_SplitWord("b");
+  if (*s3) {
+    *key = s3;
+  }
+  else {
+    *key = s2;
+  }
+}
+
+
diff --git a/src/plugins/alias/tests/offsets/array1.c b/src/plugins/alias/tests/offsets/array1.c
new file mode 100644
index 0000000000000000000000000000000000000000..34518455ecb6fae2be23331c1a9a3a1ba0251135
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/array1.c
@@ -0,0 +1,15 @@
+// simple array
+//  {x, y} are aliased
+
+int main () {
+  int tab[4];
+  tab[0] = 0;
+  tab[1] = 1;
+  tab[2] = tab[1] +1;
+
+  int* x = &tab[1];
+  int* y = &tab[2];
+  tab[3] = *x + *y;
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/array2.c b/src/plugins/alias/tests/offsets/array2.c
new file mode 100644
index 0000000000000000000000000000000000000000..0ba4d222f6a4642288f2c53cfd8fcfb1d1e7b036
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/array2.c
@@ -0,0 +1,17 @@
+// matrices (this example may be not a valid c program)
+//  no alias
+
+int main () {
+  int mat[4][4];
+  mat[0][0] = 0;
+  mat[0][1] = 1;
+
+  int **x;
+  *x = mat[1];
+
+  int* y;
+  *y = *x[0];
+
+  
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/array3.c b/src/plugins/alias/tests/offsets/array3.c
new file mode 100644
index 0000000000000000000000000000000000000000..09bd2e67a51be84ef8a466417a95f88709ef8b3d
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/array3.c
@@ -0,0 +1,15 @@
+// matrices
+//  {x, y} are aliased
+ 
+#include <stdlib.h>
+
+
+int main () {
+  int mat[4][4];
+  int* x = malloc (4* sizeof(int));
+  int* y = malloc (4* sizeof(int));
+  x = mat[0];
+  y = mat[1];
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/collapse1.c b/src/plugins/alias/tests/offsets/collapse1.c
new file mode 100644
index 0000000000000000000000000000000000000000..624f42c3af68819390dbbaf141ef0452f9ba3c75
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/collapse1.c
@@ -0,0 +1,14 @@
+
+
+int main () {
+  int tab[4];
+  tab[0] = 0;
+  tab[1] = 1;
+  tab[2] = tab[1] +1;
+  int x =0;
+  
+  for (int i=0;i<2;i++)
+    x = tab[i];
+  
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/collapse2.c b/src/plugins/alias/tests/offsets/collapse2.c
new file mode 100644
index 0000000000000000000000000000000000000000..9c00bd24e3b5297f9d18a9fe99922e4a5d543802
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/collapse2.c
@@ -0,0 +1,15 @@
+// matrices
+
+int main () {
+  int mat[4][4];
+  mat[0][0] = 0;
+  mat[0][1] = 1;
+
+  int i=2;
+  mat[1][i]=i;
+
+  i=i+1;
+  mat[1][i]=2;
+  
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/collapse3.c b/src/plugins/alias/tests/offsets/collapse3.c
new file mode 100644
index 0000000000000000000000000000000000000000..8540638c809a74ad632b46ec6ce12342b30906e6
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/collapse3.c
@@ -0,0 +1,15 @@
+// matrices
+
+int main () {
+  int mat[4][4];
+  mat[0][0] = 0;
+  mat[0][1] = 1;
+
+  int i=2;
+  mat[i][1]=i;
+
+  i=i+1;
+  mat[i][1]=2;
+  
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/nested1.c b/src/plugins/alias/tests/offsets/nested1.c
new file mode 100644
index 0000000000000000000000000000000000000000..06c14b9512b4ee4d15c4451f2d22382c2703f49c
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/nested1.c
@@ -0,0 +1,56 @@
+// nested structures and arrays
+//  {z1->s, z2->s, tab_y[0]} are aliased
+//  {t->t, z1} are aliased
+//  {z1->c, t->d, a} are aliased
+//  {z2->c, b} are aliased
+
+
+#include <stdlib.h>
+
+typedef struct
+{       
+    int   a;
+    int   b;
+} st_1_t;
+
+typedef struct
+{       
+    struct struct_1_t*  s;
+    int*   c;
+} st_2_t;
+
+
+typedef struct
+{       
+    struct struct_2_t*  t;
+    int*   d;
+} st_3_t;
+
+
+
+int main () {
+
+  st_1_t x1 = {0,1};
+  st_1_t x2 = {1,2};
+  st_1_t *tab_y [2];
+
+  tab_y[0] = &x1;
+  tab_y[1] = &x2;
+  st_2_t *z1 = malloc(sizeof(st_2_t));
+  st_2_t *z2 = malloc(sizeof(st_2_t));
+  st_3_t *t = malloc(sizeof(st_3_t));
+  int* a = malloc(sizeof(int));
+  int* b = malloc(sizeof(int));
+  
+  *a = 0;
+  *b = 5;
+  z1->s = tab_y[0];
+  z2->s = tab_y[1];
+  z1->c = a;
+  z2->c = b;
+  t->t = z1;
+  t->d = a;
+  
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/nested2.c b/src/plugins/alias/tests/offsets/nested2.c
new file mode 100644
index 0000000000000000000000000000000000000000..193bdd1adba16542da95e964e384c3651c373379
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/nested2.c
@@ -0,0 +1,50 @@
+// nested structures and arrays
+//  {t->t, z1} are aliased
+//  {z1->c, t->d, a} are aliased
+
+
+#include <stdlib.h>
+
+typedef struct
+{       
+    int   a;
+    int   b;
+} st_1_t;
+
+typedef struct
+{       
+    struct struct_1_t*  s [2];
+    int*   c;
+} st_2_t;
+
+
+typedef struct
+{       
+    struct struct_2_t*  t;
+    int*   d;
+} st_3_t;
+
+
+
+
+
+int main () {
+
+  st_1_t x1 = {0,1};
+  st_1_t x2 = {2,3};
+
+  st_2_t *z1 = malloc(sizeof(st_2_t));
+
+  st_3_t *t = malloc(sizeof(st_3_t));
+  int* a = malloc(sizeof(int));
+  
+  *a = 0;
+  z1->s[0] = &x1;
+  z1->s[1] = &x2;
+  z1->c = a;
+  t->t = z1;
+  t->d = a;
+  
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/oracle/array1.res.oracle b/src/plugins/alias/tests/offsets/oracle/array1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..d6bdf7ba016ca2bf534ccbde0c2f7b0fe9f36f76
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/array1.res.oracle
@@ -0,0 +1,17 @@
+[kernel] Parsing array1.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: tab[0] = 0;
+[alias] May-aliases after instruction  tab[0] = 0;  are  <none>
+[alias] analysing instruction: tab[1] = 1;
+[alias] May-aliases after instruction  tab[1] = 1;  are  <none>
+[alias] analysing instruction: tab[2] = tab[1] + 1;
+[alias] May-aliases after instruction  tab[2] = tab[1] + 1;  are  <none>
+[alias] analysing instruction: int *x = & tab[1];
+[alias] May-aliases after instruction  int *x = & tab[1];  are  <none>
+[alias] analysing instruction: int *y = & tab[2];
+[alias] May-aliases after instruction  int *y = & tab[2];  are  {x, y}
+[alias] analysing instruction: tab[3] = *x + *y;
+[alias] May-aliases after instruction  tab[3] = *x + *y;  are  {x, y}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {x, y}
+[alias] May-aliases at the end of function main: {x, y}
diff --git a/src/plugins/alias/tests/offsets/oracle/array2.res.oracle b/src/plugins/alias/tests/offsets/oracle/array2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..69f16a022f8b05688a9a9eb66a4180354fdcf323
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/array2.res.oracle
@@ -0,0 +1,13 @@
+[kernel] Parsing array2.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: mat[0][0] = 0;
+[alias] May-aliases after instruction  mat[0][0] = 0;  are  <none>
+[alias] analysing instruction: mat[0][1] = 1;
+[alias] May-aliases after instruction  mat[0][1] = 1;  are  <none>
+[alias] analysing instruction: *x = mat[1];
+[alias] May-aliases after instruction  *x = mat[1];  are  <none>
+[alias] analysing instruction: *y = *(*(x + 0));
+[alias] May-aliases after instruction  *y = *(*(x + 0));  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/offsets/oracle/array3.res.oracle b/src/plugins/alias/tests/offsets/oracle/array3.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..6b6a66a4677d71e520481483aaa137fa7dd8529c
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/array3.res.oracle
@@ -0,0 +1,127 @@
+[kernel] Parsing array3.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: int *x = malloc((unsigned long)4 * sizeof(int));
+[alias] May-aliases after instruction
+  int *x = malloc((unsigned long)4 * sizeof(int));  are  <none>
+[alias] analysing instruction: int *y = malloc((unsigned long)4 * sizeof(int));
+[alias] May-aliases after instruction
+  int *y = malloc((unsigned long)4 * sizeof(int));  are  <none>
+[alias] analysing instruction: x = mat[0];
+[alias] May-aliases after instruction  x = mat[0];  are  <none>
+[alias] analysing instruction: y = mat[1];
+[alias] May-aliases after instruction  y = mat[1];  are  {x, y}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {x, y}
+[alias] May-aliases at the end of function main: {x, y}
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/offsets/oracle/collapse1.res.oracle b/src/plugins/alias/tests/offsets/oracle/collapse1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..9b588f2f8f2484f894680dae6ca6129528811125
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/collapse1.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing collapse1.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: tab[0] = 0;
+[alias] May-aliases after instruction  tab[0] = 0;  are  <none>
+[alias] analysing instruction: tab[1] = 1;
+[alias] May-aliases after instruction  tab[1] = 1;  are  <none>
+[alias] analysing instruction: tab[2] = tab[1] + 1;
+[alias] May-aliases after instruction  tab[2] = tab[1] + 1;  are  <none>
+[alias] analysing instruction: int x = 0;
+[alias] May-aliases after instruction  int x = 0;  are  <none>
+[alias] analysing instruction: int i = 0;
+[alias] May-aliases after instruction  int i = 0;  are  <none>
+[alias] analysing instruction: x = tab[i];
+[alias] May-aliases after instruction  x = tab[i];  are  <none>
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/offsets/oracle/collapse2.res.oracle b/src/plugins/alias/tests/offsets/oracle/collapse2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..34b8bd11975081e1acc6cd63c7d0011d1f3b57e3
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/collapse2.res.oracle
@@ -0,0 +1,17 @@
+[kernel] Parsing collapse2.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: mat[0][0] = 0;
+[alias] May-aliases after instruction  mat[0][0] = 0;  are  <none>
+[alias] analysing instruction: mat[0][1] = 1;
+[alias] May-aliases after instruction  mat[0][1] = 1;  are  <none>
+[alias] analysing instruction: int i = 2;
+[alias] May-aliases after instruction  int i = 2;  are  <none>
+[alias] analysing instruction: mat[1][i] = i;
+[alias] May-aliases after instruction  mat[1][i] = i;  are  <none>
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are  <none>
+[alias] analysing instruction: mat[1][i] = 2;
+[alias] May-aliases after instruction  mat[1][i] = 2;  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/offsets/oracle/collapse3.res.oracle b/src/plugins/alias/tests/offsets/oracle/collapse3.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..4193c3f90a212238b3a6f1452d58e097c1ae1bd1
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/collapse3.res.oracle
@@ -0,0 +1,17 @@
+[kernel] Parsing collapse3.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: mat[0][0] = 0;
+[alias] May-aliases after instruction  mat[0][0] = 0;  are  <none>
+[alias] analysing instruction: mat[0][1] = 1;
+[alias] May-aliases after instruction  mat[0][1] = 1;  are  <none>
+[alias] analysing instruction: int i = 2;
+[alias] May-aliases after instruction  int i = 2;  are  <none>
+[alias] analysing instruction: mat[i][1] = i;
+[alias] May-aliases after instruction  mat[i][1] = i;  are  <none>
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are  <none>
+[alias] analysing instruction: mat[i][1] = 2;
+[alias] May-aliases after instruction  mat[i][1] = 2;  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/offsets/oracle/nested1.res.oracle b/src/plugins/alias/tests/offsets/oracle/nested1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..e26a96622ddd53633ec3d0978ac43635f1dc1e4f
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/nested1.res.oracle
@@ -0,0 +1,168 @@
+[kernel] Parsing nested1.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1};
+[alias] May-aliases after instruction  st_1_t x1 = {.a = 0, .b = 1};  are  <none>
+[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2};
+[alias] May-aliases after instruction  st_1_t x2 = {.a = 1, .b = 2};  are  <none>
+[alias] analysing instruction: tab_y[0] = & x1;
+[alias] May-aliases after instruction  tab_y[0] = & x1;  are  <none>
+[alias] analysing instruction: tab_y[1] = & x2;
+[alias] May-aliases after instruction  tab_y[1] = & x2;  are  <none>
+[alias] analysing instruction: st_2_t *z1 = malloc(sizeof(st_2_t));
+[alias] May-aliases after instruction  st_2_t *z1 = malloc(sizeof(st_2_t));  are
+  <none>
+[alias] analysing instruction: st_2_t *z2 = malloc(sizeof(st_2_t));
+[alias] May-aliases after instruction  st_2_t *z2 = malloc(sizeof(st_2_t));  are
+  <none>
+[alias] analysing instruction: st_3_t *t = malloc(sizeof(st_3_t));
+[alias] May-aliases after instruction  st_3_t *t = malloc(sizeof(st_3_t));  are
+  <none>
+[alias] analysing instruction: int *a = malloc(sizeof(int));
+[alias] May-aliases after instruction  int *a = malloc(sizeof(int));  are  <none>
+[alias] analysing instruction: int *b = malloc(sizeof(int));
+[alias] May-aliases after instruction  int *b = malloc(sizeof(int));  are  <none>
+[alias] analysing instruction: *a = 0;
+[alias] May-aliases after instruction  *a = 0;  are  <none>
+[alias] analysing instruction: *b = 5;
+[alias] May-aliases after instruction  *b = 5;  are  <none>
+[alias] analysing instruction: z1->s = (struct struct_1_t *)tab_y[0];
+[alias:unsafe-cast] nested1.c:47: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction  z1->s = (struct struct_1_t *)tab_y[0];  are
+  {z1->s, tab_y[0]}
+[alias] analysing instruction: z2->s = (struct struct_1_t *)tab_y[1];
+[alias:unsafe-cast] nested1.c:48: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction  z2->s = (struct struct_1_t *)tab_y[1];  are
+  {z1->s, z2->s, tab_y[0]}
+[alias] analysing instruction: z1->c = a;
+[alias] May-aliases after instruction  z1->c = a;  are
+  {z1->s, z2->s, tab_y[0]}  {z1->c, a}
+[alias] analysing instruction: z2->c = b;
+[alias] May-aliases after instruction  z2->c = b;  are
+  {z1->s, z2->s, tab_y[0]}  {z1->c, a}  {z2->c, b}
+[alias] analysing instruction: t->t = (struct struct_2_t *)z1;
+[alias:unsafe-cast] nested1.c:51: Warning: 
+  unsafe cast from st_2_t * to struct struct_2_t *
+[alias] May-aliases after instruction  t->t = (struct struct_2_t *)z1;  are
+  {z1->s, z2->s, tab_y[0]}  {t->t, z1}  {z1->c, a}  {z2->c, b}
+[alias] analysing instruction: t->d = a;
+[alias] May-aliases after instruction  t->d = a;  are
+  {z1->s, z2->s, tab_y[0]}  {t->t, z1}  {z1->c, t->d, a}  {z2->c, b}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are
+  {z1->s, z2->s, tab_y[0]}  {t->t, z1}  {z1->c, t->d, a}  {z2->c, b}
+[alias] May-aliases at the end of function main:
+  {z1->s, z2->s, tab_y[0]}  {t->t, z1}  {z1->c, t->d, a}  {z2->c, b}
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/offsets/oracle/nested2.res.oracle b/src/plugins/alias/tests/offsets/oracle/nested2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..7167c4aebae1c65a02d1333dd738a7c9cccc658c
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/nested2.res.oracle
@@ -0,0 +1,151 @@
+[kernel] Parsing nested2.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1};
+[alias] May-aliases after instruction  st_1_t x1 = {.a = 0, .b = 1};  are  <none>
+[alias] analysing instruction: st_1_t x2 = {.a = 2, .b = 3};
+[alias] May-aliases after instruction  st_1_t x2 = {.a = 2, .b = 3};  are  <none>
+[alias] analysing instruction: st_2_t *z1 = malloc(sizeof(st_2_t));
+[alias] May-aliases after instruction  st_2_t *z1 = malloc(sizeof(st_2_t));  are
+  <none>
+[alias] analysing instruction: st_3_t *t = malloc(sizeof(st_3_t));
+[alias] May-aliases after instruction  st_3_t *t = malloc(sizeof(st_3_t));  are
+  <none>
+[alias] analysing instruction: int *a = malloc(sizeof(int));
+[alias] May-aliases after instruction  int *a = malloc(sizeof(int));  are  <none>
+[alias] analysing instruction: *a = 0;
+[alias] May-aliases after instruction  *a = 0;  are  <none>
+[alias] analysing instruction: z1->s[0] = (struct struct_1_t *)(& x1);
+[alias:unsafe-cast] nested2.c:42: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction  z1->s[0] = (struct struct_1_t *)(& x1);  are
+  <none>
+[alias] analysing instruction: z1->s[1] = (struct struct_1_t *)(& x2);
+[alias:unsafe-cast] nested2.c:43: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction  z1->s[1] = (struct struct_1_t *)(& x2);  are
+  <none>
+[alias] analysing instruction: z1->c = a;
+[alias] May-aliases after instruction  z1->c = a;  are  {z1->c, a}
+[alias] analysing instruction: t->t = (struct struct_2_t *)z1;
+[alias:unsafe-cast] nested2.c:45: Warning: 
+  unsafe cast from st_2_t * to struct struct_2_t *
+[alias] May-aliases after instruction  t->t = (struct struct_2_t *)z1;  are
+  {t->t, z1}  {z1->c, a}
+[alias] analysing instruction: t->d = a;
+[alias] May-aliases after instruction  t->d = a;  are  {t->t, z1}  {z1->c, t->d, a}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are
+  {t->t, z1}  {z1->c, t->d, a}
+[alias] May-aliases at the end of function main: {t->t, z1}  {z1->c, t->d, a}
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/offsets/oracle/structure1.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..6fab8c1f99d32876d28e448212a5a4a026a7809c
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/structure1.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing structure1.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: st_1_t x = {.a = 0, .b = 1};
+[alias] May-aliases after instruction  st_1_t x = {.a = 0, .b = 1};  are  <none>
+[alias] analysing instruction: st_2_t y = {.a = 3, .c = 4};
+[alias] May-aliases after instruction  st_2_t y = {.a = 3, .c = 4};  are  <none>
+[alias] analysing instruction: st_1_t *p_x = & x;
+[alias] May-aliases after instruction  st_1_t *p_x = & x;  are  <none>
+[alias] analysing instruction: st_2_t *p_y = & y;
+[alias] May-aliases after instruction  st_2_t *p_y = & y;  are  <none>
+[alias] analysing instruction: p_x->a = 3;
+[alias] May-aliases after instruction  p_x->a = 3;  are  <none>
+[alias] analysing instruction: p_x = (st_1_t *)p_y;
+[alias:unsafe-cast] structure1.c:28: Warning: 
+  unsafe cast from st_2_t * to st_1_t *
+[alias] May-aliases after instruction  p_x = (st_1_t *)p_y;  are  {p_x, p_y}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {p_x, p_y}
+[alias] May-aliases at the end of function main: {p_x, p_y}
diff --git a/src/plugins/alias/tests/offsets/oracle/structure2.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..2b2f7ecd4e531f1ec02f3d115396b6b6f0de27d0
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/structure2.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing structure2.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1};
+[alias] May-aliases after instruction  st_1_t x1 = {.a = 0, .b = 1};  are  <none>
+[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2};
+[alias] May-aliases after instruction  st_1_t x2 = {.a = 1, .b = 2};  are  <none>
+[alias] analysing instruction: st_2_t y = {.s = (struct struct_1_t *)(& x1), .c = 4};
+[alias:unsafe-cast] structure2.c:21: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction
+  st_2_t y = {.s = (struct struct_1_t *)(& x1), .c = 4};  are  <none>
+[alias] analysing instruction: y.s = (struct struct_1_t *)(& x2);
+[alias:unsafe-cast] structure2.c:23: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction  y.s = (struct struct_1_t *)(& x2);  are
+  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/offsets/oracle/structure3.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure3.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..7ec86d402cb6980ff01296b3901039b234b94464
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/structure3.res.oracle
@@ -0,0 +1,33 @@
+[kernel] Parsing structure3.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1};
+[alias] May-aliases after instruction  st_1_t x1 = {.a = 0, .b = 1};  are  <none>
+[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2};
+[alias] May-aliases after instruction  st_1_t x2 = {.a = 1, .b = 2};  are  <none>
+[alias] analysing instruction:
+  st_2_t y1 = {.s = (struct struct_1_t *)(& x1), .c = 3};
+[alias:unsafe-cast] structure3.c:31: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction
+  st_2_t y1 = {.s = (struct struct_1_t *)(& x1), .c = 3};  are  <none>
+[alias] analysing instruction:
+  st_2_t y2 = {.s = (struct struct_1_t *)(& x2), .c = 4};
+[alias:unsafe-cast] structure3.c:32: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction
+  st_2_t y2 = {.s = (struct struct_1_t *)(& x2), .c = 4};  are  <none>
+[alias] analysing instruction: st_3_t z = {.t = (struct struct_2_t *)(& y1), .d = 5};
+[alias:unsafe-cast] structure3.c:33: Warning: 
+  unsafe cast from st_2_t * to struct struct_2_t *
+[alias] May-aliases after instruction
+  st_3_t z = {.t = (struct struct_2_t *)(& y1), .d = 5};  are  <none>
+[alias] analysing instruction: z.t = (struct struct_2_t *)(& y2);
+[alias:unsafe-cast] structure3.c:35: Warning: 
+  unsafe cast from st_2_t * to struct struct_2_t *
+[alias] May-aliases after instruction  z.t = (struct struct_2_t *)(& y2);  are
+  <none>
+[alias] analysing instruction: y1.c = z.d;
+[alias] May-aliases after instruction  y1.c = z.d;  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/offsets/oracle/structure4.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure4.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..17d462a32e0c6ec88e3c3c03b6c82ae0b907a465
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/structure4.res.oracle
@@ -0,0 +1,136 @@
+[kernel] Parsing structure4.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1};
+[alias] May-aliases after instruction  st_1_t x1 = {.a = 0, .b = 1};  are  <none>
+[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2};
+[alias] May-aliases after instruction  st_1_t x2 = {.a = 1, .b = 2};  are  <none>
+[alias] analysing instruction: st_1_t *y1 = malloc(sizeof(st_1_t));
+[alias] May-aliases after instruction  st_1_t *y1 = malloc(sizeof(st_1_t));  are
+  <none>
+[alias] analysing instruction: st_2_t *z = malloc(sizeof(st_2_t));
+[alias] May-aliases after instruction  st_2_t *z = malloc(sizeof(st_2_t));  are
+  <none>
+[alias] analysing instruction: y1 = & x1;
+[alias] May-aliases after instruction  y1 = & x1;  are  <none>
+[alias] analysing instruction: z->s = (struct struct_1_t *)y1;
+[alias:unsafe-cast] structure4.c:37: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction  z->s = (struct struct_1_t *)y1;  are
+  {z->s, y1}
+[alias] analysing instruction: z->c = 6;
+[alias] May-aliases after instruction  z->c = 6;  are  {z->s, y1}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {z->s, y1}
+[alias] May-aliases at the end of function main: {z->s, y1}
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/offsets/oracle/structure5.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure5.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..6ab3b8478904bba3396ee4bf1314b90cb372fb45
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/structure5.res.oracle
@@ -0,0 +1,153 @@
+[kernel] Parsing structure5.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1};
+[alias] May-aliases after instruction  st_1_t x1 = {.a = 0, .b = 1};  are  <none>
+[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2};
+[alias] May-aliases after instruction  st_1_t x2 = {.a = 1, .b = 2};  are  <none>
+[alias] analysing instruction: st_1_t *y1 = malloc(sizeof(st_1_t));
+[alias] May-aliases after instruction  st_1_t *y1 = malloc(sizeof(st_1_t));  are
+  <none>
+[alias] analysing instruction: st_2_t *z = malloc(sizeof(st_2_t));
+[alias] May-aliases after instruction  st_2_t *z = malloc(sizeof(st_2_t));  are
+  <none>
+[alias] analysing instruction: st_3_t *t = malloc(sizeof(st_3_t));
+[alias] May-aliases after instruction  st_3_t *t = malloc(sizeof(st_3_t));  are
+  <none>
+[alias] analysing instruction: int *a = malloc(sizeof(int));
+[alias] May-aliases after instruction  int *a = malloc(sizeof(int));  are  <none>
+[alias] analysing instruction: *a = 0;
+[alias] May-aliases after instruction  *a = 0;  are  <none>
+[alias] analysing instruction: y1 = & x1;
+[alias] May-aliases after instruction  y1 = & x1;  are  <none>
+[alias] analysing instruction: z->s = (struct struct_1_t *)y1;
+[alias:unsafe-cast] structure5.c:41: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction  z->s = (struct struct_1_t *)y1;  are
+  {z->s, y1}
+[alias] analysing instruction: z->c = a;
+[alias] May-aliases after instruction  z->c = a;  are  {z->s, y1}  {z->c, a}
+[alias] analysing instruction: t->t = (struct struct_2_t *)z;
+[alias:unsafe-cast] structure5.c:43: Warning: 
+  unsafe cast from st_2_t * to struct struct_2_t *
+[alias] May-aliases after instruction  t->t = (struct struct_2_t *)z;  are
+  {z->s, y1}  {t->t, z}  {z->c, a}
+[alias] analysing instruction: t->d = a;
+[alias] May-aliases after instruction  t->d = a;  are
+  {z->s, y1}  {t->t, z}  {z->c, t->d, a}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are
+  {z->s, y1}  {t->t, z}  {z->c, t->d, a}
+[alias] May-aliases at the end of function main:
+  {z->s, y1}  {t->t, z}  {z->c, t->d, a}
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/offsets/structure1.c b/src/plugins/alias/tests/offsets/structure1.c
new file mode 100644
index 0000000000000000000000000000000000000000..95cf272878359073767764d7340b0546eb21f65c
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/structure1.c
@@ -0,0 +1,30 @@
+// simple structure
+//  {p_x, p_y} are aliased
+
+
+typedef struct
+{       
+    int   a;
+    int   b;
+} st_1_t;
+
+typedef struct
+{       
+    int   a;
+    int   c;
+} st_2_t;
+
+
+int main () {
+
+  st_1_t x = {0,1};
+  st_2_t y = {3,4};
+
+  st_1_t * p_x = &x;
+  st_2_t * p_y = &y;
+
+  
+  p_x->a = 3;
+  p_x = p_y; 
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/structure2.c b/src/plugins/alias/tests/offsets/structure2.c
new file mode 100644
index 0000000000000000000000000000000000000000..92ff3a41783f5e35b94622b1ebe1553946938e7a
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/structure2.c
@@ -0,0 +1,26 @@
+// structure with initialisation and pointer
+//  no alias
+
+typedef struct
+{       
+    int   a;
+    int   b;
+} st_1_t;
+
+typedef struct
+{       
+    struct struct_1_t*  s;
+    int   c;
+} st_2_t;
+
+
+int main () {
+
+  st_1_t x1 = {0,1};
+  st_1_t x2 = {1,2};
+  st_2_t y = {&x1,4};
+
+  y.s = &x2;
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/structure3.c b/src/plugins/alias/tests/offsets/structure3.c
new file mode 100644
index 0000000000000000000000000000000000000000..9582ccd3f86dfe6b9b186213836c29aee37a600f
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/structure3.c
@@ -0,0 +1,39 @@
+// double structure with initialisation and pointer
+//  no alias
+
+typedef struct
+{       
+    int   a;
+    int   b;
+} st_1_t;
+
+typedef struct
+{       
+    struct struct_1_t*  s;
+    int   c;
+} st_2_t;
+
+
+typedef struct
+{       
+    struct struct_2_t*  t;
+    int   d;
+} st_3_t;
+
+
+
+
+
+int main () {
+
+  st_1_t x1 = {0,1};
+  st_1_t x2 = {1,2};
+  st_2_t y1 = {&x1,3};
+  st_2_t y2 = {&x2,4};
+  st_3_t z = {&y1,5};
+  
+  z.t = &y2;
+  y1.c = z.d;
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/structure4.c b/src/plugins/alias/tests/offsets/structure4.c
new file mode 100644
index 0000000000000000000000000000000000000000..c33bce757fec2a73fa1a55d075081c9955fa14a7
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/structure4.c
@@ -0,0 +1,41 @@
+// structure with malloc
+//  {z->s, y1} are aliased
+
+#include <stdlib.h>
+
+typedef struct
+{       
+    int   a;
+    int   b;
+} st_1_t;
+
+typedef struct
+{       
+    struct struct_1_t*  s;
+    int   c;
+} st_2_t;
+
+
+typedef struct
+{       
+    struct struct_2_t*  t;
+    int   d;
+} st_3_t;
+
+
+
+
+
+int main () {
+
+  st_1_t x1 = {0,1};
+  st_1_t x2 = {1,2};
+  st_1_t *y1 = malloc(sizeof(st_1_t));
+  st_2_t *z = malloc(sizeof(st_2_t));
+
+  y1 = &x1;
+  z->s = y1;
+  z->c = 6;
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/structure5.c b/src/plugins/alias/tests/offsets/structure5.c
new file mode 100644
index 0000000000000000000000000000000000000000..eeeefafd63d3518a65fbc88f0f96bb456104f94d
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/structure5.c
@@ -0,0 +1,48 @@
+// another structure, more complex
+//  {z->s, y1} are aliased
+//  {t->t, z} are aliased
+//  {z->c, t->d, a} are aliased
+
+
+#include <stdlib.h>
+
+typedef struct
+{       
+    int   a;
+    int   b;
+} st_1_t;
+
+typedef struct
+{       
+    struct struct_1_t*  s;
+    int*   c;
+} st_2_t;
+
+
+typedef struct
+{       
+    struct struct_2_t*  t;
+    int*   d;
+} st_3_t;
+
+
+
+int main () {
+
+  st_1_t x1 = {0,1};
+  st_1_t x2 = {1,2};
+  st_1_t *y1 = malloc(sizeof(st_1_t));
+  st_2_t *z = malloc(sizeof(st_2_t));
+  st_3_t *t = malloc(sizeof(st_3_t));
+  int* a = malloc(sizeof(int));
+  
+  *a = 0;
+  y1 = &x1;
+  z->s = y1;
+  z->c = a;
+  t->t = z;
+  t->d = a;
+  
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/ptests_config b/src/plugins/alias/tests/ptests_config
new file mode 100644
index 0000000000000000000000000000000000000000..364f24e63e59237f7800393fbdf9829fc9330471
--- /dev/null
+++ b/src/plugins/alias/tests/ptests_config
@@ -0,0 +1 @@
+DEFAULT_SUITES=basic real_world offsets fixed_bugs
diff --git a/src/plugins/alias/tests/real_world/example1.c b/src/plugins/alias/tests/real_world/example1.c
new file mode 100644
index 0000000000000000000000000000000000000000..a3709a6736725db096563ff80de05329276ef3aa
--- /dev/null
+++ b/src/plugins/alias/tests/real_world/example1.c
@@ -0,0 +1,108 @@
+// real world example
+//  {a->t1[0], b->t1[0]} are aliased
+//  {a->t2[0], b->t2[0]} are aliased
+//  {a->n1, b->n1} are aliased
+//  {a->n2, b->n2} are aliased
+
+
+#include <stdlib.h>
+#include <math.h>
+
+typedef struct {
+  double *t1[2];
+  double *t2[2];
+  int *n1;
+  int *n2;
+} ty;
+
+void swap(int *n)
+{
+  if ((*n) == 1) {
+    (*n) = 0;
+  }
+  else {
+    (*n)++;
+  }
+}
+
+
+void *f1(ty *x)
+{
+  ty *tmp = x;
+  double *idata;
+  double *odata;
+  int idx;
+
+  idata = (double *)malloc(10 * sizeof(double));
+
+  while (1) {
+
+    idata = tmp->t2[*tmp->n2];
+
+    odata = tmp->t1[*tmp->n1];
+
+    for (idx = 0; idx < 10; idx++) {
+      odata[idx] = 0.5*sin(idata[idx]);
+    }
+    swap(tmp->n1);
+  }
+  return (void *) NULL;
+}
+
+
+void *f2(ty *x)
+{
+  ty *tmp = x;
+  int idx;
+  double *idata;
+  double *odata;
+
+  idata = (double*)malloc(10* sizeof(double));
+
+  while (1) {
+
+    idata = tmp->t1[*tmp->n1];
+
+    odata = tmp->t2[*tmp->n2];
+
+    for (idx = 0; idx < 10; idx++) {
+          odata[idx] = 3*idata[idx] + 1;
+    }
+    swap(tmp->n2);
+  }
+
+  return (void *) NULL;
+}
+
+
+int main(void)
+{
+  ty *a;
+  ty *b;
+
+  a = (ty *)malloc(sizeof(ty));
+  b = (ty *)malloc(sizeof(ty));
+
+  int i;
+  for (i = 0; i < 2; i++) {
+      a->t1[i] = (double *)malloc(10 * sizeof(double));
+      a->t2[i] = (double *)malloc(10 * sizeof(double));
+  }
+
+  a->n1 = (int *)malloc(sizeof(int));
+  a->n2 = (int *)malloc(sizeof(int));
+  *a->n1 = 1;
+  *a->n2 = 1;
+
+  for (i = 0; i < 2; i++) {
+    b->t1[i] = a->t1[i];
+    b->t2[i] = a->t2[i];
+  }
+  b->n1 = a->n1;
+  b->n2 = a->n2;
+
+  f1(a);
+  f2(b);
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/real_world/example2.c b/src/plugins/alias/tests/real_world/example2.c
new file mode 100644
index 0000000000000000000000000000000000000000..18e08504e7c44a69853a32bf94ed52404942a5ec
--- /dev/null
+++ b/src/plugins/alias/tests/real_world/example2.c
@@ -0,0 +1,108 @@
+// real world example
+//  {a->t1[0], b->t1[0]} are aliased
+//  {a->t2[0], b->t2[0]} are aliased
+//  {a->n1, b->n1} are aliased
+//  {a->n2, b->n2} are aliased
+
+
+#include <stdlib.h>
+#include <math.h>
+
+typedef struct {
+  double *t1[2];
+  double *t2[2];
+  int *n1;
+  int *n2;
+} ty;
+
+void swap(int *n)
+{
+  if ((*n) == 1) {
+    (*n) = 0;
+  }
+  else {
+    (*n)++;
+  }
+}
+
+
+void *f1(ty *x)
+{
+  ty *tmp = x;
+  double *idata;
+  double *odata;
+  int idx;
+
+  idata = (double *)malloc(10 * sizeof(double));
+
+  for (int i = 0; i < 2; i++) {
+
+    idata = tmp->t2[*tmp->n2];
+
+    odata = tmp->t1[*tmp->n1];
+
+    for (idx = 0; idx < 10; idx++) {
+      odata[idx] = 0.5*sin(idata[idx]);
+    }
+    swap(tmp->n1);
+  }
+  return (void *) NULL;
+}
+
+
+void *f2(ty *x)
+{
+  ty *tmp = x;
+  int idx;
+  double *idata;
+  double *odata;
+
+  idata = (double*)malloc(10* sizeof(double));
+
+  for (int i = 0; i < 2; i++) {
+
+    idata = tmp->t1[*tmp->n1];
+
+    odata = tmp->t2[*tmp->n2];
+
+    for (idx = 0; idx < 10; idx++) {
+          odata[idx] = 3*idata[idx] + 1;
+    }
+    swap(tmp->n2);
+  }
+
+  return (void *) NULL;
+}
+
+
+int main(void)
+{
+  ty *a;
+  ty *b;
+
+  a = (ty *)malloc(sizeof(ty));
+  b = (ty *)malloc(sizeof(ty));
+
+  int i;
+  for (i = 0; i < 2; i++) {
+      a->t1[i] = (double *)malloc(10 * sizeof(double));
+      a->t2[i] = (double *)malloc(10 * sizeof(double));
+  }
+
+  a->n1 = (int *)malloc(sizeof(int));
+  a->n2 = (int *)malloc(sizeof(int));
+  *a->n1 = 1;
+  *a->n2 = 1;
+
+  for (i = 0; i < 2; i++) {
+    b->t1[i] = a->t1[i];
+    b->t2[i] = a->t2[i];
+  }
+  b->n1 = a->n1;
+  b->n2 = a->n2;
+
+  f1(a);
+  f2(b);
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/real_world/function1_v2.c b/src/plugins/alias/tests/real_world/function1_v2.c
new file mode 100644
index 0000000000000000000000000000000000000000..3187998b7574e374a2a14dfa89ff10f8f6342763
--- /dev/null
+++ b/src/plugins/alias/tests/real_world/function1_v2.c
@@ -0,0 +1,26 @@
+// function with no return
+//  {a, b} are aliased
+//  {c, d} are aliased
+//#include <stdio.h>
+#include <stdlib.h>
+
+void alias(int **x, int **y) {
+  *x = *y;
+}
+
+
+int main(void)
+{
+  int *a = malloc(sizeof(int));
+  *a = 0;
+  int *b = malloc(sizeof(int));;
+  *b = 42;
+  
+  alias(&a,&b);
+
+  *a = 7;
+  //printf("a = %d && b = %d\n",*a,*b);
+
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/real_world/oracle/example1.res.old b/src/plugins/alias/tests/real_world/oracle/example1.res.old
new file mode 100644
index 0000000000000000000000000000000000000000..97708d154b7fc3fc196c5926743747fe2f6276d9
--- /dev/null
+++ b/src/plugins/alias/tests/real_world/oracle/example1.res.old
@@ -0,0 +1,403 @@
+[kernel] Parsing example1.c (with preprocessing)
+[alias] Parsing done
+[alias] Skipping assignment idata = tmp->t2[*(tmp->n2)] (not implemented)
+[alias] Skipping assignment odata = tmp->t1[*(tmp->n1)] (not implemented)
+[alias] In a function call, parameter (x <- *(idata + idx)) is ignored)
+[alias] Warning: a function with no return is employed in an assignment
+[alias] Skipping assignment *(odata + idx) = 0.5 * tmp_1 (BUG do_assignment 2)
+[alias] In a function call, parameter (x <- *(idata + idx)) is ignored)
+[alias] Warning: a function with no return is employed in an assignment
+[alias] Skipping assignment *(odata + idx) = 0.5 * tmp_1 (BUG do_assignment 2)
+[alias] Skipping assignment idata = tmp->t2[*(tmp->n2)] (not implemented)
+[alias] Skipping assignment odata = tmp->t1[*(tmp->n1)] (not implemented)
+[alias] Warning: DEBUG return stmt of f1 not in table
+[alias] Warning: Analysis is continuing but will not be sound
+[alias] Skipping assignment idata = tmp->t1[*(tmp->n1)] (not implemented)
+[alias] Skipping assignment odata = tmp->t2[*(tmp->n2)] (not implemented)
+[alias] Skipping assignment *(odata + idx) = (double)3 * *(idata + idx) + (double)1 (BUG do_assignment 2)
+[alias] Skipping assignment *(odata + idx) = (double)3 * *(idata + idx) + (double)1 (BUG do_assignment 2)
+[alias] Skipping assignment idata = tmp->t1[*(tmp->n1)] (not implemented)
+[alias] Skipping assignment odata = tmp->t2[*(tmp->n2)] (not implemented)
+[alias] Warning: DEBUG return stmt of f2 not in table
+[alias] Warning: Analysis is continuing but will not be sound
+[alias] Skipping assignment a->t1[i] = malloc() (not implemented)
+[alias] Skipping assignment a->t2[i] = malloc() (not implemented)
+[alias] Skipping assignment a->t1[i] = malloc() (not implemented)
+[alias] Skipping assignment a->t2[i] = malloc() (not implemented)
+[alias] Skipping assignment a->n1 = malloc() (not implemented)
+[alias] Skipping assignment a->n2 = malloc() (not implemented)
+[alias] May-aliases at the end of function main:
+  <list of may-alias>
+  {b.n1; b; } are aliased
+  {b.n1; b.n2; b; } are aliased
+  {*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased
+  <end of list>
+[alias] Functions done
+Before statement b->t1[i] = a->t1[i]; :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; } are aliased
+<end of list>
+
+Before statement idx = 0; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement b->t2[i] = a->t2[i]; :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; } are aliased
+<end of list>
+
+Before statement while (idx < 10) {
+                   *(odata + idx) = (double)3 * *(idata + idx) + (double)1;
+                   idx ++;
+                 } :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement if (*n == 1) *n = 0; else (*n) ++; :
+ <list of may-alias>
+<end of list>
+
+Before statement i ++; :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; } are aliased
+<end of list>
+
+Before statement if (*n == 1) *n = 0; else (*n) ++; :
+ <list of may-alias>
+<end of list>
+
+Before statement b->n1 = a->n1; :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; } are aliased
+<end of list>
+
+Before statement if (! (idx < 10)) break; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement *n = 0; :
+ <list of may-alias>
+<end of list>
+
+Before statement b->n2 = a->n2; :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b; } are aliased
+{b.n1; b; } are aliased
+<end of list>
+
+Before statement break; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement (*n) ++; :
+ <list of may-alias>
+<end of list>
+
+Before statement f1(a); :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased
+{b.n1; b; } are aliased
+{b.n1; b.n2; b; } are aliased
+<end of list>
+
+Before statement *(odata + idx) = (double)3 * *(idata + idx) + (double)1; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement f2(b); :
+ <list of may-alias>
+{b.n1; b; } are aliased
+{b.n1; b.n2; b; } are aliased
+{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased
+<end of list>
+
+Before statement *(odata + idx) = (double)3 * *(idata + idx) + (double)1; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement __retres = 0; :
+ <list of may-alias>
+{b.n1; b; } are aliased
+{b.n1; b.n2; b; } are aliased
+{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased
+<end of list>
+
+Before statement idx ++; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement ty *tmp = x; :
+ <list of may-alias>
+<end of list>
+
+Before statement swap(tmp->n2); :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement idata = (double *)malloc((unsigned long)10 * sizeof(double)); :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement return; :
+ <list of may-alias>
+<end of list>
+
+Before statement while (1) {
+                   idata = tmp->t2[*(tmp->n2)];
+                   odata = tmp->t1[*(tmp->n1)];
+                   idx = 0;
+                   while (idx < 10) {
+                     {
+                       double tmp_1;
+                       tmp_1 = sin(*(idata + idx));
+                       *(odata + idx) = 0.5 * tmp_1;
+                     }
+                     idx ++;
+                   }
+                   swap(tmp->n1);
+                 } :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement idata = tmp->t2[*(tmp->n2)];
+                 odata = tmp->t1[*(tmp->n1)];
+                 idx = 0;
+                 while (idx < 10) {
+                   {
+                     double tmp_1;
+                     tmp_1 = sin(*(idata + idx));
+                     *(odata + idx) = 0.5 * tmp_1;
+                   }
+                   idx ++;
+                 }
+                 swap(tmp->n1); :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement a = (ty *)malloc(sizeof(ty)); :
+ <list of may-alias>
+<end of list>
+
+Before statement idata = tmp->t2[*(tmp->n2)]; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement b = (ty *)malloc(sizeof(ty)); :
+ <list of may-alias>
+<end of list>
+
+Before statement odata = tmp->t1[*(tmp->n1)]; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement i = 0; :
+ <list of may-alias>
+<end of list>
+
+Before statement idx = 0; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement while (i < 2) {
+                   a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+                   a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+                   i ++;
+                 } :
+ <list of may-alias>
+<end of list>
+
+Before statement while (idx < 10) {
+                   {
+                     double tmp_1;
+                     tmp_1 = sin(*(idata + idx));
+                     *(odata + idx) = 0.5 * tmp_1;
+                   }
+                   idx ++;
+                 } :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement return __retres; :
+ <list of may-alias>
+{b.n1; b; } are aliased
+{b.n1; b.n2; b; } are aliased
+{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased
+<end of list>
+
+Before statement if (! (i < 2)) break; :
+ <list of may-alias>
+<end of list>
+
+Before statement if (! (idx < 10)) break; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement break; :
+ <list of may-alias>
+<end of list>
+
+Before statement break; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+                 a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); :
+ <list of may-alias>
+<end of list>
+
+Before statement {
+                   double tmp_1;
+                   tmp_1 = sin(*(idata + idx));
+                   *(odata + idx) = 0.5 * tmp_1;
+                 } :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); :
+ <list of may-alias>
+<end of list>
+
+Before statement tmp_1 = sin(*(idata + idx));
+                 *(odata + idx) = 0.5 * tmp_1; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); :
+ <list of may-alias>
+<end of list>
+
+Before statement tmp_1 = sin(*(idata + idx)); :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement i ++; :
+ <list of may-alias>
+<end of list>
+
+Before statement *(odata + idx) = 0.5 * tmp_1; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement a->n1 = (int *)malloc(sizeof(int)); :
+ <list of may-alias>
+<end of list>
+
+Before statement idx ++; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement a->n2 = (int *)malloc(sizeof(int)); :
+ <list of may-alias>
+<end of list>
+
+Before statement swap(tmp->n1); :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement *(a->n1) = 1; :
+ <list of may-alias>
+<end of list>
+
+Before statement *(a->n2) = 1; :
+ <list of may-alias>
+<end of list>
+
+Before statement i = 0; :
+ <list of may-alias>
+<end of list>
+
+Before statement ty *tmp = x; :
+ <list of may-alias>
+<end of list>
+
+Before statement while (i < 2) {
+                   b->t1[i] = a->t1[i];
+                   b->t2[i] = a->t2[i];
+                   i ++;
+                 } :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; } are aliased
+<end of list>
+
+Before statement idata = (double *)malloc((unsigned long)10 * sizeof(double)); :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement while (1) {
+                   idata = tmp->t1[*(tmp->n1)];
+                   odata = tmp->t2[*(tmp->n2)];
+                   idx = 0;
+                   while (idx < 10) {
+                     *(odata + idx) = (double)3 * *(idata + idx) + (double)1;
+                     idx ++;
+                   }
+                   swap(tmp->n2);
+                 } :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement if (! (i < 2)) break; :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; } are aliased
+<end of list>
+
+Before statement idata = tmp->t1[*(tmp->n1)];
+                 odata = tmp->t2[*(tmp->n2)];
+                 idx = 0;
+                 while (idx < 10) {
+                   *(odata + idx) = (double)3 * *(idata + idx) + (double)1;
+                   idx ++;
+                 }
+                 swap(tmp->n2); :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement break; :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; } are aliased
+<end of list>
+
+Before statement idata = tmp->t1[*(tmp->n1)]; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement b->t1[i] = a->t1[i];
+                 b->t2[i] = a->t2[i]; :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; } are aliased
+<end of list>
+
+Before statement odata = tmp->t2[*(tmp->n2)]; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+[alias] Analysis complete
diff --git a/src/plugins/alias/tests/real_world/oracle/example1.res.oracle b/src/plugins/alias/tests/real_world/oracle/example1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..2184e66ef66ccd9e68cdee8db84944dbaa773d5f
--- /dev/null
+++ b/src/plugins/alias/tests/real_world/oracle/example1.res.oracle
@@ -0,0 +1,412 @@
+[kernel] Parsing example1.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: __fc_fpclassify
+[alias] May-aliases at the end of function __fc_fpclassify: ⊥
+[alias] analysing function: __fc_fpclassifyf
+[alias] May-aliases at the end of function __fc_fpclassifyf: ⊥
+[alias] analysing function: __fc_infinity
+[alias] May-aliases at the end of function __fc_infinity: ⊥
+[alias] analysing function: __fc_nan
+[alias] May-aliases at the end of function __fc_nan: ⊥
+[alias] analysing function: __finite
+[alias] May-aliases at the end of function __finite: ⊥
+[alias] analysing function: __finitef
+[alias] May-aliases at the end of function __finitef: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: acos
+[alias] May-aliases at the end of function acos: ⊥
+[alias] analysing function: acosf
+[alias] May-aliases at the end of function acosf: ⊥
+[alias] analysing function: acosh
+[alias] May-aliases at the end of function acosh: ⊥
+[alias] analysing function: acoshf
+[alias] May-aliases at the end of function acoshf: ⊥
+[alias] analysing function: acoshl
+[alias] May-aliases at the end of function acoshl: ⊥
+[alias] analysing function: acosl
+[alias] May-aliases at the end of function acosl: ⊥
+[alias] analysing function: asin
+[alias] May-aliases at the end of function asin: ⊥
+[alias] analysing function: asinf
+[alias] May-aliases at the end of function asinf: ⊥
+[alias] analysing function: asinl
+[alias] May-aliases at the end of function asinl: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atan
+[alias] May-aliases at the end of function atan: ⊥
+[alias] analysing function: atan2
+[alias] May-aliases at the end of function atan2: ⊥
+[alias] analysing function: atan2f
+[alias] May-aliases at the end of function atan2f: ⊥
+[alias] analysing function: atan2l
+[alias] May-aliases at the end of function atan2l: ⊥
+[alias] analysing function: atanf
+[alias] May-aliases at the end of function atanf: ⊥
+[alias] analysing function: atanl
+[alias] May-aliases at the end of function atanl: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: ceil
+[alias] May-aliases at the end of function ceil: ⊥
+[alias] analysing function: ceilf
+[alias] May-aliases at the end of function ceilf: ⊥
+[alias] analysing function: ceill
+[alias] May-aliases at the end of function ceill: ⊥
+[alias] analysing function: cos
+[alias] May-aliases at the end of function cos: ⊥
+[alias] analysing function: cosf
+[alias] May-aliases at the end of function cosf: ⊥
+[alias] analysing function: cosl
+[alias] May-aliases at the end of function cosl: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: exp
+[alias] May-aliases at the end of function exp: ⊥
+[alias] analysing function: expf
+[alias] May-aliases at the end of function expf: ⊥
+[alias] analysing function: f1
+[alias] analysing instruction: ty *tmp = x;
+[alias] May-aliases after instruction  ty *tmp = x;  are  {x, tmp}
+[alias] analysing instruction:
+  idata = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  idata = (double *)malloc((unsigned long)10 * sizeof(double));  are  {x, tmp}
+[alias] analysing instruction: idata = tmp->t2[*(tmp->n2)];
+[alias] May-aliases after instruction  idata = tmp->t2[*(tmp->n2)];  are
+  {x, tmp}  {tmp->t2[0], idata}
+[alias] analysing instruction: odata = tmp->t1[*(tmp->n1)];
+[alias] May-aliases after instruction  odata = tmp->t1[*(tmp->n1)];  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: idx = 0;
+[alias] May-aliases after instruction  idx = 0;  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: tmp_1 = sin(*(idata + idx));
+[alias] analysing function: sin
+[alias] May-aliases at the end of function sin: ⊥
+[alias:undefined:fn] example1.c:45: Warning: function sin has no definition
+[alias] May-aliases after instruction  tmp_1 = sin(*(idata + idx));  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: *(odata + idx) = 0.5 * tmp_1;
+[alias] May-aliases after instruction  *(odata + idx) = 0.5 * tmp_1;  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: idx ++;
+[alias] May-aliases after instruction  idx ++;  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: swap(tmp->n1);
+[alias] analysing function: swap
+[alias] analysing instruction: *n = 0;
+[alias] May-aliases after instruction  *n = 0;  are  <none>
+[alias] analysing instruction: (*n) ++;
+[alias] May-aliases after instruction  (*n) ++;  are  <none>
+[alias] May-aliases at the end of function swap: <none>
+[alias] May-aliases after instruction  swap(tmp->n1);  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: idata = tmp->t2[*(tmp->n2)];
+[alias] May-aliases after instruction  idata = tmp->t2[*(tmp->n2)];  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: odata = tmp->t1[*(tmp->n1)];
+[alias] May-aliases after instruction  odata = tmp->t1[*(tmp->n1)];  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias:no-return] example1.c:29: Warning: 
+  function f1 does not return; analysis may be unsound
+[alias] May-aliases at the end of function f1: <none>
+[alias] analysing function: f2
+[alias] analysing instruction: ty *tmp = x;
+[alias] May-aliases after instruction  ty *tmp = x;  are  {x, tmp}
+[alias] analysing instruction:
+  idata = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  idata = (double *)malloc((unsigned long)10 * sizeof(double));  are  {x, tmp}
+[alias] analysing instruction: idata = tmp->t1[*(tmp->n1)];
+[alias] May-aliases after instruction  idata = tmp->t1[*(tmp->n1)];  are
+  {x, tmp}  {tmp->t1[0], idata}
+[alias] analysing instruction: odata = tmp->t2[*(tmp->n2)];
+[alias] May-aliases after instruction  odata = tmp->t2[*(tmp->n2)];  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: idx = 0;
+[alias] May-aliases after instruction  idx = 0;  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction:
+  *(odata + idx) = (double)3 * *(idata + idx) + (double)1;
+[alias] May-aliases after instruction
+  *(odata + idx) = (double)3 * *(idata + idx) + (double)1;  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: idx ++;
+[alias] May-aliases after instruction  idx ++;  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: swap(tmp->n2);
+[alias] May-aliases after instruction  swap(tmp->n2);  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: idata = tmp->t1[*(tmp->n1)];
+[alias] May-aliases after instruction  idata = tmp->t1[*(tmp->n1)];  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: odata = tmp->t2[*(tmp->n2)];
+[alias] May-aliases after instruction  odata = tmp->t2[*(tmp->n2)];  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias:no-return] example1.c:53: Warning: 
+  function f2 does not return; analysis may be unsound
+[alias] May-aliases at the end of function f2: <none>
+[alias] analysing function: fabs
+[alias] May-aliases at the end of function fabs: ⊥
+[alias] analysing function: fabsf
+[alias] May-aliases at the end of function fabsf: ⊥
+[alias] analysing function: fabsl
+[alias] May-aliases at the end of function fabsl: ⊥
+[alias] analysing function: floor
+[alias] May-aliases at the end of function floor: ⊥
+[alias] analysing function: floorf
+[alias] May-aliases at the end of function floorf: ⊥
+[alias] analysing function: floorl
+[alias] May-aliases at the end of function floorl: ⊥
+[alias] analysing function: fmod
+[alias] May-aliases at the end of function fmod: ⊥
+[alias] analysing function: fmodf
+[alias] May-aliases at the end of function fmodf: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: frexp
+[alias] May-aliases at the end of function frexp: ⊥
+[alias] analysing function: frexpf
+[alias] May-aliases at the end of function frexpf: ⊥
+[alias] analysing function: frexpl
+[alias] May-aliases at the end of function frexpl: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldexp
+[alias] May-aliases at the end of function ldexp: ⊥
+[alias] analysing function: ldexpf
+[alias] May-aliases at the end of function ldexpf: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: log
+[alias] May-aliases at the end of function log: ⊥
+[alias] analysing function: log10
+[alias] May-aliases at the end of function log10: ⊥
+[alias] analysing function: log10f
+[alias] May-aliases at the end of function log10f: ⊥
+[alias] analysing function: log10l
+[alias] May-aliases at the end of function log10l: ⊥
+[alias] analysing function: log2
+[alias] May-aliases at the end of function log2: ⊥
+[alias] analysing function: log2f
+[alias] May-aliases at the end of function log2f: ⊥
+[alias] analysing function: log2l
+[alias] May-aliases at the end of function log2l: ⊥
+[alias] analysing function: logf
+[alias] May-aliases at the end of function logf: ⊥
+[alias] analysing function: logl
+[alias] May-aliases at the end of function logl: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: a = (ty *)malloc(sizeof(ty));
+[alias] May-aliases after instruction  a = (ty *)malloc(sizeof(ty));  are  <none>
+[alias] analysing instruction: b = (ty *)malloc(sizeof(ty));
+[alias] May-aliases after instruction  b = (ty *)malloc(sizeof(ty));  are  <none>
+[alias] analysing instruction: i = 0;
+[alias] May-aliases after instruction  i = 0;  are  <none>
+[alias] analysing instruction:
+  a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));  are  
+  <none>
+[alias] analysing instruction:
+  a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));  are  
+  <none>
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are  <none>
+[alias] analysing instruction:
+  a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));  are  
+  <none>
+[alias] analysing instruction:
+  a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));  are  
+  <none>
+[alias] analysing instruction: a->n1 = (int *)malloc(sizeof(int));
+[alias] May-aliases after instruction  a->n1 = (int *)malloc(sizeof(int));  are
+  <none>
+[alias] analysing instruction: a->n2 = (int *)malloc(sizeof(int));
+[alias] May-aliases after instruction  a->n2 = (int *)malloc(sizeof(int));  are
+  <none>
+[alias] analysing instruction: *(a->n1) = 1;
+[alias] May-aliases after instruction  *(a->n1) = 1;  are  <none>
+[alias] analysing instruction: *(a->n2) = 1;
+[alias] May-aliases after instruction  *(a->n2) = 1;  are  <none>
+[alias] analysing instruction: i = 0;
+[alias] May-aliases after instruction  i = 0;  are  <none>
+[alias] analysing instruction: b->t1[i] = a->t1[i];
+[alias] May-aliases after instruction  b->t1[i] = a->t1[i];  are
+  {a->t1[0], b->t1[0]}
+[alias] analysing instruction: b->t2[i] = a->t2[i];
+[alias] May-aliases after instruction  b->t2[i] = a->t2[i];  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}
+[alias] analysing instruction: b->t1[i] = a->t1[i];
+[alias] May-aliases after instruction  b->t1[i] = a->t1[i];  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}
+[alias] analysing instruction: b->t2[i] = a->t2[i];
+[alias] May-aliases after instruction  b->t2[i] = a->t2[i];  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}
+[alias] analysing instruction: b->n1 = a->n1;
+[alias] May-aliases after instruction  b->n1 = a->n1;  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}
+[alias] analysing instruction: b->n2 = a->n2;
+[alias] May-aliases after instruction  b->n2 = a->n2;  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] analysing instruction: f1(a);
+[alias] May-aliases after instruction  f1(a);  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] analysing instruction: f2(b);
+[alias] May-aliases after instruction  f2(b);  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] May-aliases at the end of function main:
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nan
+[alias] May-aliases at the end of function nan: ⊥
+[alias] analysing function: nanf
+[alias] May-aliases at the end of function nanf: ⊥
+[alias] analysing function: nanl
+[alias] May-aliases at the end of function nanl: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: pow
+[alias] May-aliases at the end of function pow: ⊥
+[alias] analysing function: powf
+[alias] May-aliases at the end of function powf: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: round
+[alias] May-aliases at the end of function round: ⊥
+[alias] analysing function: roundf
+[alias] May-aliases at the end of function roundf: ⊥
+[alias] analysing function: roundl
+[alias] May-aliases at the end of function roundl: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: sin
+[alias] May-aliases at the end of function sin: ⊥
+[alias] analysing function: sinf
+[alias] May-aliases at the end of function sinf: ⊥
+[alias] analysing function: sinl
+[alias] May-aliases at the end of function sinl: ⊥
+[alias] analysing function: sqrt
+[alias] May-aliases at the end of function sqrt: ⊥
+[alias] analysing function: sqrtf
+[alias] May-aliases at the end of function sqrtf: ⊥
+[alias] analysing function: sqrtl
+[alias] May-aliases at the end of function sqrtl: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: swap
+[alias] May-aliases at the end of function swap: <none>
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: tan
+[alias] May-aliases at the end of function tan: ⊥
+[alias] analysing function: tanf
+[alias] May-aliases at the end of function tanf: ⊥
+[alias] analysing function: tanl
+[alias] May-aliases at the end of function tanl: ⊥
+[alias] analysing function: trunc
+[alias] May-aliases at the end of function trunc: ⊥
+[alias] analysing function: truncf
+[alias] May-aliases at the end of function truncf: ⊥
+[alias] analysing function: truncl
+[alias] May-aliases at the end of function truncl: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/real_world/oracle/example2.res.oracle b/src/plugins/alias/tests/real_world/oracle/example2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..21f8829b4dc8c670f933cedca6281dd899cd434f
--- /dev/null
+++ b/src/plugins/alias/tests/real_world/oracle/example2.res.oracle
@@ -0,0 +1,426 @@
+[kernel] Parsing example2.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: __fc_fpclassify
+[alias] May-aliases at the end of function __fc_fpclassify: ⊥
+[alias] analysing function: __fc_fpclassifyf
+[alias] May-aliases at the end of function __fc_fpclassifyf: ⊥
+[alias] analysing function: __fc_infinity
+[alias] May-aliases at the end of function __fc_infinity: ⊥
+[alias] analysing function: __fc_nan
+[alias] May-aliases at the end of function __fc_nan: ⊥
+[alias] analysing function: __finite
+[alias] May-aliases at the end of function __finite: ⊥
+[alias] analysing function: __finitef
+[alias] May-aliases at the end of function __finitef: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: acos
+[alias] May-aliases at the end of function acos: ⊥
+[alias] analysing function: acosf
+[alias] May-aliases at the end of function acosf: ⊥
+[alias] analysing function: acosh
+[alias] May-aliases at the end of function acosh: ⊥
+[alias] analysing function: acoshf
+[alias] May-aliases at the end of function acoshf: ⊥
+[alias] analysing function: acoshl
+[alias] May-aliases at the end of function acoshl: ⊥
+[alias] analysing function: acosl
+[alias] May-aliases at the end of function acosl: ⊥
+[alias] analysing function: asin
+[alias] May-aliases at the end of function asin: ⊥
+[alias] analysing function: asinf
+[alias] May-aliases at the end of function asinf: ⊥
+[alias] analysing function: asinl
+[alias] May-aliases at the end of function asinl: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atan
+[alias] May-aliases at the end of function atan: ⊥
+[alias] analysing function: atan2
+[alias] May-aliases at the end of function atan2: ⊥
+[alias] analysing function: atan2f
+[alias] May-aliases at the end of function atan2f: ⊥
+[alias] analysing function: atan2l
+[alias] May-aliases at the end of function atan2l: ⊥
+[alias] analysing function: atanf
+[alias] May-aliases at the end of function atanf: ⊥
+[alias] analysing function: atanl
+[alias] May-aliases at the end of function atanl: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: ceil
+[alias] May-aliases at the end of function ceil: ⊥
+[alias] analysing function: ceilf
+[alias] May-aliases at the end of function ceilf: ⊥
+[alias] analysing function: ceill
+[alias] May-aliases at the end of function ceill: ⊥
+[alias] analysing function: cos
+[alias] May-aliases at the end of function cos: ⊥
+[alias] analysing function: cosf
+[alias] May-aliases at the end of function cosf: ⊥
+[alias] analysing function: cosl
+[alias] May-aliases at the end of function cosl: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: exp
+[alias] May-aliases at the end of function exp: ⊥
+[alias] analysing function: expf
+[alias] May-aliases at the end of function expf: ⊥
+[alias] analysing function: f1
+[alias] analysing instruction: ty *tmp = x;
+[alias] May-aliases after instruction  ty *tmp = x;  are  {x, tmp}
+[alias] analysing instruction:
+  idata = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  idata = (double *)malloc((unsigned long)10 * sizeof(double));  are  {x, tmp}
+[alias] analysing instruction: int i = 0;
+[alias] May-aliases after instruction  int i = 0;  are  {x, tmp}
+[alias] analysing instruction: idata = tmp->t2[*(tmp->n2)];
+[alias] May-aliases after instruction  idata = tmp->t2[*(tmp->n2)];  are
+  {x, tmp}  {tmp->t2[0], idata}
+[alias] analysing instruction: odata = tmp->t1[*(tmp->n1)];
+[alias] May-aliases after instruction  odata = tmp->t1[*(tmp->n1)];  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: idx = 0;
+[alias] May-aliases after instruction  idx = 0;  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: tmp_1 = sin(*(idata + idx));
+[alias] analysing function: sin
+[alias] May-aliases at the end of function sin: ⊥
+[alias:undefined:fn] example2.c:45: Warning: function sin has no definition
+[alias] May-aliases after instruction  tmp_1 = sin(*(idata + idx));  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: *(odata + idx) = 0.5 * tmp_1;
+[alias] May-aliases after instruction  *(odata + idx) = 0.5 * tmp_1;  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: idx ++;
+[alias] May-aliases after instruction  idx ++;  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: swap(tmp->n1);
+[alias] analysing function: swap
+[alias] analysing instruction: *n = 0;
+[alias] May-aliases after instruction  *n = 0;  are  <none>
+[alias] analysing instruction: (*n) ++;
+[alias] May-aliases after instruction  (*n) ++;  are  <none>
+[alias] May-aliases at the end of function swap: <none>
+[alias] May-aliases after instruction  swap(tmp->n1);  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: idata = tmp->t2[*(tmp->n2)];
+[alias] May-aliases after instruction  idata = tmp->t2[*(tmp->n2)];  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: odata = tmp->t1[*(tmp->n1)];
+[alias] May-aliases after instruction  odata = tmp->t1[*(tmp->n1)];  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: __retres = (void *)0;
+[alias] May-aliases after instruction  __retres = (void *)0;  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] May-aliases at the end of function f1:
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing function: f2
+[alias] analysing instruction: ty *tmp = x;
+[alias] May-aliases after instruction  ty *tmp = x;  are  {x, tmp}
+[alias] analysing instruction:
+  idata = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  idata = (double *)malloc((unsigned long)10 * sizeof(double));  are  {x, tmp}
+[alias] analysing instruction: int i = 0;
+[alias] May-aliases after instruction  int i = 0;  are  {x, tmp}
+[alias] analysing instruction: idata = tmp->t1[*(tmp->n1)];
+[alias] May-aliases after instruction  idata = tmp->t1[*(tmp->n1)];  are
+  {x, tmp}  {tmp->t1[0], idata}
+[alias] analysing instruction: odata = tmp->t2[*(tmp->n2)];
+[alias] May-aliases after instruction  odata = tmp->t2[*(tmp->n2)];  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: idx = 0;
+[alias] May-aliases after instruction  idx = 0;  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction:
+  *(odata + idx) = (double)3 * *(idata + idx) + (double)1;
+[alias] May-aliases after instruction
+  *(odata + idx) = (double)3 * *(idata + idx) + (double)1;  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: idx ++;
+[alias] May-aliases after instruction  idx ++;  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: swap(tmp->n2);
+[alias] May-aliases after instruction  swap(tmp->n2);  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: idata = tmp->t1[*(tmp->n1)];
+[alias] May-aliases after instruction  idata = tmp->t1[*(tmp->n1)];  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: odata = tmp->t2[*(tmp->n2)];
+[alias] May-aliases after instruction  odata = tmp->t2[*(tmp->n2)];  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: __retres = (void *)0;
+[alias] May-aliases after instruction  __retres = (void *)0;  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] May-aliases at the end of function f2:
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing function: fabs
+[alias] May-aliases at the end of function fabs: ⊥
+[alias] analysing function: fabsf
+[alias] May-aliases at the end of function fabsf: ⊥
+[alias] analysing function: fabsl
+[alias] May-aliases at the end of function fabsl: ⊥
+[alias] analysing function: floor
+[alias] May-aliases at the end of function floor: ⊥
+[alias] analysing function: floorf
+[alias] May-aliases at the end of function floorf: ⊥
+[alias] analysing function: floorl
+[alias] May-aliases at the end of function floorl: ⊥
+[alias] analysing function: fmod
+[alias] May-aliases at the end of function fmod: ⊥
+[alias] analysing function: fmodf
+[alias] May-aliases at the end of function fmodf: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: frexp
+[alias] May-aliases at the end of function frexp: ⊥
+[alias] analysing function: frexpf
+[alias] May-aliases at the end of function frexpf: ⊥
+[alias] analysing function: frexpl
+[alias] May-aliases at the end of function frexpl: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldexp
+[alias] May-aliases at the end of function ldexp: ⊥
+[alias] analysing function: ldexpf
+[alias] May-aliases at the end of function ldexpf: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: log
+[alias] May-aliases at the end of function log: ⊥
+[alias] analysing function: log10
+[alias] May-aliases at the end of function log10: ⊥
+[alias] analysing function: log10f
+[alias] May-aliases at the end of function log10f: ⊥
+[alias] analysing function: log10l
+[alias] May-aliases at the end of function log10l: ⊥
+[alias] analysing function: log2
+[alias] May-aliases at the end of function log2: ⊥
+[alias] analysing function: log2f
+[alias] May-aliases at the end of function log2f: ⊥
+[alias] analysing function: log2l
+[alias] May-aliases at the end of function log2l: ⊥
+[alias] analysing function: logf
+[alias] May-aliases at the end of function logf: ⊥
+[alias] analysing function: logl
+[alias] May-aliases at the end of function logl: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: a = (ty *)malloc(sizeof(ty));
+[alias] May-aliases after instruction  a = (ty *)malloc(sizeof(ty));  are  <none>
+[alias] analysing instruction: b = (ty *)malloc(sizeof(ty));
+[alias] May-aliases after instruction  b = (ty *)malloc(sizeof(ty));  are  <none>
+[alias] analysing instruction: i = 0;
+[alias] May-aliases after instruction  i = 0;  are  <none>
+[alias] analysing instruction:
+  a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));  are  
+  <none>
+[alias] analysing instruction:
+  a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));  are  
+  <none>
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are  <none>
+[alias] analysing instruction:
+  a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));  are  
+  <none>
+[alias] analysing instruction:
+  a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));  are  
+  <none>
+[alias] analysing instruction: a->n1 = (int *)malloc(sizeof(int));
+[alias] May-aliases after instruction  a->n1 = (int *)malloc(sizeof(int));  are
+  <none>
+[alias] analysing instruction: a->n2 = (int *)malloc(sizeof(int));
+[alias] May-aliases after instruction  a->n2 = (int *)malloc(sizeof(int));  are
+  <none>
+[alias] analysing instruction: *(a->n1) = 1;
+[alias] May-aliases after instruction  *(a->n1) = 1;  are  <none>
+[alias] analysing instruction: *(a->n2) = 1;
+[alias] May-aliases after instruction  *(a->n2) = 1;  are  <none>
+[alias] analysing instruction: i = 0;
+[alias] May-aliases after instruction  i = 0;  are  <none>
+[alias] analysing instruction: b->t1[i] = a->t1[i];
+[alias] May-aliases after instruction  b->t1[i] = a->t1[i];  are
+  {a->t1[0], b->t1[0]}
+[alias] analysing instruction: b->t2[i] = a->t2[i];
+[alias] May-aliases after instruction  b->t2[i] = a->t2[i];  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}
+[alias] analysing instruction: b->t1[i] = a->t1[i];
+[alias] May-aliases after instruction  b->t1[i] = a->t1[i];  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}
+[alias] analysing instruction: b->t2[i] = a->t2[i];
+[alias] May-aliases after instruction  b->t2[i] = a->t2[i];  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}
+[alias] analysing instruction: b->n1 = a->n1;
+[alias] May-aliases after instruction  b->n1 = a->n1;  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}
+[alias] analysing instruction: b->n2 = a->n2;
+[alias] May-aliases after instruction  b->n2 = a->n2;  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] analysing instruction: f1(a);
+[alias] May-aliases after instruction  f1(a);  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] analysing instruction: f2(b);
+[alias] May-aliases after instruction  f2(b);  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] May-aliases at the end of function main:
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nan
+[alias] May-aliases at the end of function nan: ⊥
+[alias] analysing function: nanf
+[alias] May-aliases at the end of function nanf: ⊥
+[alias] analysing function: nanl
+[alias] May-aliases at the end of function nanl: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: pow
+[alias] May-aliases at the end of function pow: ⊥
+[alias] analysing function: powf
+[alias] May-aliases at the end of function powf: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: round
+[alias] May-aliases at the end of function round: ⊥
+[alias] analysing function: roundf
+[alias] May-aliases at the end of function roundf: ⊥
+[alias] analysing function: roundl
+[alias] May-aliases at the end of function roundl: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: sin
+[alias] May-aliases at the end of function sin: ⊥
+[alias] analysing function: sinf
+[alias] May-aliases at the end of function sinf: ⊥
+[alias] analysing function: sinl
+[alias] May-aliases at the end of function sinl: ⊥
+[alias] analysing function: sqrt
+[alias] May-aliases at the end of function sqrt: ⊥
+[alias] analysing function: sqrtf
+[alias] May-aliases at the end of function sqrtf: ⊥
+[alias] analysing function: sqrtl
+[alias] May-aliases at the end of function sqrtl: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: swap
+[alias] May-aliases at the end of function swap: <none>
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: tan
+[alias] May-aliases at the end of function tan: ⊥
+[alias] analysing function: tanf
+[alias] May-aliases at the end of function tanf: ⊥
+[alias] analysing function: tanl
+[alias] May-aliases at the end of function tanl: ⊥
+[alias] analysing function: trunc
+[alias] May-aliases at the end of function trunc: ⊥
+[alias] analysing function: truncf
+[alias] May-aliases at the end of function truncf: ⊥
+[alias] analysing function: truncl
+[alias] May-aliases at the end of function truncl: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/real_world/oracle/function1_v2.res.oracle b/src/plugins/alias/tests/real_world/oracle/function1_v2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..029211f36e3c5e5788b1656bc41836f8e6628d8b
--- /dev/null
+++ b/src/plugins/alias/tests/real_world/oracle/function1_v2.res.oracle
@@ -0,0 +1,133 @@
+[kernel] Parsing function1_v2.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: alias
+[alias] analysing instruction: *x = *y;
+[alias] May-aliases after instruction  *x = *y;  are  {x, y}
+[alias] May-aliases at the end of function alias: {x, y}
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: int *a = malloc(sizeof(int));
+[alias] May-aliases after instruction  int *a = malloc(sizeof(int));  are  <none>
+[alias] analysing instruction: *a = 0;
+[alias] May-aliases after instruction  *a = 0;  are  <none>
+[alias] analysing instruction: int *b = malloc(sizeof(int));
+[alias] May-aliases after instruction  int *b = malloc(sizeof(int));  are  <none>
+[alias] analysing instruction: *b = 42;
+[alias] May-aliases after instruction  *b = 42;  are  <none>
+[alias] analysing instruction: alias(& a,& b);
+[alias] May-aliases after instruction  alias(& a,& b);  are  {a, b}
+[alias] analysing instruction: *a = 7;
+[alias] May-aliases after instruction  *a = 7;  are  {a, b}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b}
+[alias] May-aliases at the end of function main: {a, b}
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/test_config b/src/plugins/alias/tests/test_config
new file mode 100644
index 0000000000000000000000000000000000000000..e14c0a6d24720b60c9a29eb36a4bb4cd432e5b55
--- /dev/null
+++ b/src/plugins/alias/tests/test_config
@@ -0,0 +1,2 @@
+PLUGIN: alias
+OPT: -alias -alias-verbose 3
diff --git a/src/plugins/alias/tests/unsupported/asm.c b/src/plugins/alias/tests/unsupported/asm.c
new file mode 100644
index 0000000000000000000000000000000000000000..ba2e80cb752079eb603e6a82baf938ea40e72804
--- /dev/null
+++ b/src/plugins/alias/tests/unsupported/asm.c
@@ -0,0 +1,4 @@
+int main () {
+	asm("movq %0, %%rsi");
+	return 0;
+}
diff --git a/src/plugins/alias/tests/unsupported/explicit_pointer.c b/src/plugins/alias/tests/unsupported/explicit_pointer.c
new file mode 100644
index 0000000000000000000000000000000000000000..a0b5e8f2c516d9f042cb31a6870bf803430a770c
--- /dev/null
+++ b/src/plugins/alias/tests/unsupported/explicit_pointer.c
@@ -0,0 +1,3 @@
+int main () {
+  return *((int*)1);
+}
diff --git a/src/plugins/alias/tests/unsupported/pointer_call.c b/src/plugins/alias/tests/unsupported/pointer_call.c
new file mode 100644
index 0000000000000000000000000000000000000000..448ec0f752f68628673aafccdb70969d51f5a381
--- /dev/null
+++ b/src/plugins/alias/tests/unsupported/pointer_call.c
@@ -0,0 +1,8 @@
+int f () {
+  return 0;
+}
+
+int main () {
+  int (*p)() = &f;
+  return ((*p)());
+}
diff --git a/src/plugins/aorai/aorai_utils.ml b/src/plugins/aorai/aorai_utils.ml
index 573db999ec22e60c90ab492d18531f505abb1695..23685c5dde7f246d2bc7d5a4e0e9a82308f19d3d 100644
--- a/src/plugins/aorai/aorai_utils.ml
+++ b/src/plugins/aorai/aorai_utils.ml
@@ -399,8 +399,14 @@ let rec term_to_exp t res =
   | TConst (LWStr l) -> new_exp ~loc (Const (CWStr l))
   | TConst (LChr c) -> new_exp ~loc (Const (CChr c))
   | TConst (LReal l_real) ->
-    (* r_nearest is by definition in double precision. *)
-    new_exp ~loc (Const (CReal (l_real.r_nearest, FDouble, None)))
+    let fk,_ = Floating_point.parse l_real.r_literal in
+    let cst =
+      if Cil.isExactFloat fk l_real then
+        (CReal (l_real.r_nearest, fk, Some l_real.r_literal))
+      else (* fallback to double, r_nearest being in that format anyways *)
+        (CReal (l_real.r_nearest, FDouble, None))
+    in
+    new_exp ~loc (Const cst)
   | TConst (LEnum e) -> new_exp ~loc (Const (CEnum e))
   | TLval tlval -> new_exp ~loc (Lval (tlval_to_lval tlval res))
   | TSizeOf ty -> new_exp ~loc (SizeOf ty)
@@ -413,6 +419,14 @@ let rec term_to_exp t res =
   | TBinOp (binop, t1, t2)->
     new_exp ~loc
       (BinOp(binop, term_to_exp t1 res, term_to_exp t2 res, Cil.intType))
+  | TCastE(ty, {term_node = TConst(LReal lreal)}) when Cil.isFloatingType ty ->
+    (match Cil.unrollType ty with
+     | TFloat(fk,_) ->
+       new_exp ~loc
+         (Const (CReal (lreal.r_nearest,fk,Some lreal.r_literal)))
+     | _ ->
+       Aorai_option.fatal
+         "A floating-point type was expected, got %a." Printer.pp_typ ty)
   | TCastE (ty, t) -> new_exp ~loc (CastE (ty, term_to_exp t res))
   | TAddrOf tlval -> new_exp ~loc (AddrOf (tlval_to_lval tlval res))
   | TStartOf tlval -> new_exp ~loc (StartOf (tlval_to_lval tlval res))
@@ -691,7 +705,7 @@ let mk_gvar ?init ~ty name =
   let vi =
     try
       let ty' = typeAddAttributes [Attr ("ghost", [])] ty in
-      let vi = Globals.Vars.find_from_astinfo name VGlobal in
+      let vi = Globals.Vars.find_from_astinfo name Global in
       if not (Cil_datatype.Typ.equal vi.vtype ty') then
         Aorai_option.abort "Global %s is declared with type %a instead of %a"
           name Cil_printer.pp_typ vi.vtype Cil_printer.pp_typ ty';
@@ -1092,7 +1106,8 @@ let make_enum_states () =
          (id, item))
       state_list
   in
-  set_enum mapping
+  set_enum mapping;
+  enum
 
 let getInitialState () =
   let loc = Cil_datatype.Location.unknown in
@@ -1107,7 +1122,11 @@ let initGlobals root complete =
   mk_global_comment "//* ";
   mk_global_comment "//* ";
   mk_global_comment "//* Some constants";
-  if Aorai_option.Deterministic.get () then make_enum_states ();
+  let states_typ =
+    if Aorai_option.Deterministic.get ()
+    then Some (TEnum (make_enum_states (), []))
+    else None
+  in
   (* non deterministic mode uses one variable for each possible state *)
   mk_global_c_enum_type
     listOp
@@ -1121,7 +1140,7 @@ let initGlobals root complete =
   mk_global_comment "//* ";
   mk_global_comment "//* States and Trans Variables";
   if Aorai_option.Deterministic.get () then begin
-    mk_gvar_scalar ~init:(getInitialState()) curState;
+    mk_gvar_scalar ?ty:states_typ ~init:(getInitialState()) curState;
     let init = getInitialState() (* TODO a distinct initial value for history *)
     and history = Data_for_aorai.whole_history () in
     List.iter (fun name -> mk_gvar_scalar ~init name) history
diff --git a/src/plugins/aorai/aorai_utils.mli b/src/plugins/aorai/aorai_utils.mli
index 56342ff89887091c242b6916b0c9a94f411640a0..bdbec9e51989210ea99a9a93f866795f3f0feea4 100644
--- a/src/plugins/aorai/aorai_utils.mli
+++ b/src/plugins/aorai/aorai_utils.mli
@@ -192,8 +192,6 @@ val mk_offseted_array_states_as_enum :
     (usually a fresh quantified variable). *)
 val mk_term_from_vi : Cil_types.varinfo -> Cil_types.term
 
-val make_enum_states: unit -> unit
-
 (*
 Local Variables:
 compile-command: "make -C ../../.."
diff --git a/src/plugins/aorai/data_for_aorai.ml b/src/plugins/aorai/data_for_aorai.ml
index 946814ea430bd373bd35fd4c41f79f64985de108..919b0cc253acadb481fc44a9495fe281ec351663 100644
--- a/src/plugins/aorai/data_for_aorai.ml
+++ b/src/plugins/aorai/data_for_aorai.ml
@@ -258,7 +258,7 @@ let getNumberOfStates () =
 
 
 let is_c_global name =
-  try ignore (Globals.Vars.find_from_astinfo name VGlobal); true
+  try ignore (Globals.Vars.find_from_astinfo name Global); true
   with Not_found ->
   try ignore (Globals.Functions.find_by_name name); true
   with Not_found -> false
@@ -580,11 +580,11 @@ let memo_aux_variable tr counter used_prms vi =
 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)
+    Globals.Syntactic_search.find_in_scope ~strict:true s (Formal kf) |>
+    (Fun.flip Option.bind
+       (fun vi ->
+          if top then Some (Logic_const.tvar (Cil.cvar_to_lvar vi))
+          else Some (memo_aux_variable tr counter used_prms vi)))
   | EReturn kf when top && ( Datatype.String.equal s "return"
                              || Datatype.String.equal s "\\result") ->
     let rt = Kernel_function.get_return_type kf in
@@ -619,11 +619,11 @@ let find_in_env env counter s =
               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)
+       (match Globals.Syntactic_search.find_in_scope s Program with
+        | Some vi -> Logic_const.tvar (Cil.cvar_to_lvar vi)
+        | None -> Aorai_option.abort "Unknown variable %s" s)
      with
-       M.Found lv -> lv
-     | Not_found -> Aorai_option.abort "Unknown variable %s" s)
+       M.Found lv -> lv)
 
 let find_prm_in_env env ?tr counter f x =
   let kf =
@@ -669,9 +669,11 @@ let find_prm_in_env env ?tr counter f x =
               (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
+          match
+            Globals.Syntactic_search.find_in_scope ~strict:true x (Formal kf)
+          with
+          | Some vi -> vi
+          | None -> 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.
@@ -908,11 +910,15 @@ let type_expr metaenv env ?tr ?current e =
 
 let type_cond needs_pebble metaenv env tr cond =
   let current = if needs_pebble then Some tr.stop else None in
+  let loc = Cil_datatype.Location.unknown in
   let rec aux pos env =
     function
     | PRel(rel,e1,e2) ->
       let env, e1, c1 = type_expr metaenv env ~tr ?current e1 in
       let env, e2, c2 = type_expr metaenv env ~tr ?current e2 in
+      let rt = LTyping.conditional_conversion loc (Some rel) e1 e2 in
+      let e1 = LTyping.mk_cast e1 rt in
+      let e2 = LTyping.mk_cast e2 rt 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 call_cond rel else tor call_cond rel in
diff --git a/src/plugins/aorai/tests/Aorai_test.ml b/src/plugins/aorai/tests/Aorai_test.ml
index c151f0839ac55b440e2113a5ee07d7b3aa39a2dd..5cd54943e86d5589f36fa80cd8d86f13d30b4266 100644
--- a/src/plugins/aorai/tests/Aorai_test.ml
+++ b/src/plugins/aorai/tests/Aorai_test.ml
@@ -121,8 +121,10 @@ let extend () =
         if InternalWpShare.is_set() then
           Wp.Wp_parameters.Share.set (InternalWpShare.get());
         Wp.Wp_parameters.Let.off();
-        Wp.Wp_parameters.Split.on();
+        Wp.Wp_parameters.SplitBranch.on();
+        Wp.Wp_parameters.SplitConj.on();
         Wp.Wp_parameters.SplitMax.set 32;
+        Wp.Wp_parameters.Model.As_string.set "+real";
         if not (Wp.Wp_parameters.Verbose.is_set()) then
           Wp.Wp_parameters.Verbose.set 0;
         Globals.Functions.iter check_auto_func;
diff --git a/src/plugins/aorai/tests/ya/floats.i b/src/plugins/aorai/tests/ya/floats.i
new file mode 100644
index 0000000000000000000000000000000000000000..84879fa708d3368a90685b68d1fb5bbcba28dfd1
--- /dev/null
+++ b/src/plugins/aorai/tests/ya/floats.i
@@ -0,0 +1,21 @@
+/* run.config*
+  STDOPT: -aorai-automata %{dep:@PTEST_DIR@/@PTEST_NAME@.ya} -then-last -eva
+*/
+
+//@ assigns \result \from x, n;
+float square_root_aux(float x, float n) {
+    float y = (x + n / x) / 2.0f;
+    if (x - y > 0.001)
+      return y;
+    else
+      return square_root_aux(y, n);
+}
+
+float square_root(float n) {
+  return square_root_aux(1.0, n);
+}
+
+void main(void)
+{
+  float r = square_root(2.0f);
+}
diff --git a/src/plugins/aorai/tests/ya/floats.ya b/src/plugins/aorai/tests/ya/floats.ya
new file mode 100644
index 0000000000000000000000000000000000000000..241b8126042ef68f60fc118cab80b824102e68a5
--- /dev/null
+++ b/src/plugins/aorai/tests/ya/floats.ya
@@ -0,0 +1,16 @@
+%init : I;
+%deterministic;
+
+I: { CALL(main) } -> A;
+
+A: { CALL(square_root) } -> B;
+
+B:
+  { square_root_aux().x >= 1.0f && square_root_aux().x <= square_root_aux().n } -> B
+| { RETURN(square_root_aux) } -> B
+| { RETURN(square_root) } -> C
+;
+
+C: { RETURN(main) } -> E;
+
+E: -> E;
diff --git a/src/plugins/aorai/tests/ya/oracle/aorai_ptr_field.res.oracle b/src/plugins/aorai/tests/ya/oracle/aorai_ptr_field.res.oracle
index e8f31d7d12c410b9fe704537bb36d02eeb706b05..37b9968d9332e932d18bd4d961fe0c8606140abc 100644
--- a/src/plugins/aorai/tests/ya/oracle/aorai_ptr_field.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/aorai_ptr_field.res.oracle
@@ -44,6 +44,7 @@ enum aorai_OpStatusList {
     int S0_tmp;
     int S1_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     S0_tmp = S0;
@@ -93,6 +94,7 @@ enum aorai_OpStatusList {
     int S0_tmp;
     int S1_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     S0_tmp = S0;
diff --git a/src/plugins/aorai/tests/ya/oracle/assigns.0.res.oracle b/src/plugins/aorai/tests/ya/oracle/assigns.0.res.oracle
index 6f35fd44384ee6713e2fcba2b8c8141febfdc79c..4c3791659969fb3fd12b879ac0ec78ad55269c7a 100644
--- a/src/plugins/aorai/tests/ya/oracle/assigns.0.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/assigns.0.res.oracle
@@ -74,6 +74,7 @@ int X;
     int Sf_tmp;
     int in_main_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_f;
     S1_tmp = S1;
@@ -153,6 +154,7 @@ int X;
     int Sf_tmp;
     int in_main_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_f;
     S1_tmp = S1;
@@ -247,6 +249,7 @@ void f(void)
     int Sf_tmp;
     int in_main_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     S1_tmp = S1;
@@ -326,6 +329,7 @@ void f(void)
     int Sf_tmp;
     int in_main_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     S1_tmp = S1;
diff --git a/src/plugins/aorai/tests/ya/oracle/assigns.1.res.oracle b/src/plugins/aorai/tests/ya/oracle/assigns.1.res.oracle
index 27d4f62301443e0894f519fc111dbdbd7132e1e9..d5aa249647d0f929f15b6ea15f3079409953728e 100644
--- a/src/plugins/aorai/tests/ya/oracle/assigns.1.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/assigns.1.res.oracle
@@ -32,7 +32,7 @@ enum aorai_OpStatusList {
 int X;
 /*@ ghost enum aorai_ListOper aorai_CurOperation; */
 /*@ ghost enum aorai_OpStatusList aorai_CurOpStatus; */
-/*@ ghost int aorai_CurStates = S1; */
+/*@ ghost enum aorai_States aorai_CurStates = S1; */
 /*@ ghost
   /@ requires aorai_CurStates ≡ Sf;
      ensures aorai_CurOpStatus ≡ aorai_Called;
@@ -71,9 +71,10 @@ int X;
   void f_pre_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_f;
-    if (3 == aorai_CurStates) aorai_CurStates = S_in_f;
+    if ((unsigned int)3 == aorai_CurStates) aorai_CurStates = S_in_f;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -118,9 +119,10 @@ int X;
   void f_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_f;
-    if (2 == aorai_CurStates) aorai_CurStates = in_main;
+    if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = in_main;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -178,9 +180,10 @@ void f(void)
   void main_pre_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
-    if (0 == aorai_CurStates) aorai_CurStates = Sf;
+    if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = Sf;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -225,9 +228,10 @@ void f(void)
   void main_post_func(int res)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
-    if (5 == aorai_CurStates) aorai_CurStates = S2;
+    if ((unsigned int)5 == aorai_CurStates) aorai_CurStates = S2;
     else aorai_CurStates = aorai_reject;
     return;
   }
diff --git a/src/plugins/aorai/tests/ya/oracle/bts1289.0.res.oracle b/src/plugins/aorai/tests/ya/oracle/bts1289.0.res.oracle
index b0cac6b01b25d96355241a543e34d95d5818b2ca..6c033979bd1de21bc5c66b78abefa5fbbecd8e26 100644
--- a/src/plugins/aorai/tests/ya/oracle/bts1289.0.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/bts1289.0.res.oracle
@@ -31,6 +31,7 @@ enum aorai_OpStatusList {
   {
     int S_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_a;
     S_tmp = S;
@@ -59,6 +60,7 @@ enum aorai_OpStatusList {
   {
     int S_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_a;
     S_tmp = S;
@@ -98,6 +100,7 @@ void a(void)
   {
     int S_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     S_tmp = S;
@@ -126,6 +129,7 @@ void a(void)
   {
     int S_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     S_tmp = S;
diff --git a/src/plugins/aorai/tests/ya/oracle/bts1289.1.res.oracle b/src/plugins/aorai/tests/ya/oracle/bts1289.1.res.oracle
index a721d8db11216ab7be3d6b63317fa08393df9473..f123a10ea1d4899ff824644d1c5a355cbde2c03f 100644
--- a/src/plugins/aorai/tests/ya/oracle/bts1289.1.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/bts1289.1.res.oracle
@@ -79,6 +79,7 @@ enum aorai_OpStatusList {
     int aorai_intermediate_state_0_tmp;
     int init_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_a;
     S_tmp = S;
@@ -166,6 +167,7 @@ enum aorai_OpStatusList {
     int aorai_intermediate_state_0_tmp;
     int init_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_a;
     S_tmp = S;
@@ -284,6 +286,7 @@ void a(void)
     int aorai_intermediate_state_0_tmp;
     int init_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     S_tmp = S;
@@ -364,6 +367,7 @@ void a(void)
     int aorai_intermediate_state_0_tmp;
     int init_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     S_tmp = S;
diff --git a/src/plugins/aorai/tests/ya/oracle/declared_function.res.oracle b/src/plugins/aorai/tests/ya/oracle/declared_function.res.oracle
index 8f274a98c57bbb554137167b38888f9cb9ad3ca4..bc1980f8dd6c6868c498af6df66a1fe4807b206b 100644
--- a/src/plugins/aorai/tests/ya/oracle/declared_function.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/declared_function.res.oracle
@@ -45,7 +45,7 @@ check lemma I_deterministic_trans{L}:
         __retres_f ≡ 1 + 2 ∧ \at(aorai_CurOperation,L) ≡ op_f ∧
         \at(aorai_CurOpStatus,L) ≡ aorai_Terminated ∧ __retres_f ≡ 0));
  */
-/*@ ghost int aorai_CurStates = I; */
+/*@ ghost enum aorai_States aorai_CurStates = I; */
 /*@ ghost
   /@ requires aorai_CurStates ≡ I;
      ensures aorai_CurOpStatus ≡ aorai_Called;
@@ -72,9 +72,10 @@ check lemma I_deterministic_trans{L}:
   void main_pre_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
-    if (0 == aorai_CurStates) aorai_CurStates = I;
+    if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = I;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -107,9 +108,10 @@ check lemma I_deterministic_trans{L}:
   void main_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
-    if (0 == aorai_CurStates) aorai_CurStates = I;
+    if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = I;
     else aorai_CurStates = aorai_reject;
     return;
   }
diff --git a/src/plugins/aorai/tests/ya/oracle/deterministic.res.oracle b/src/plugins/aorai/tests/ya/oracle/deterministic.res.oracle
index 8ad803dbd2282bf19797613d2ed3d27a25325221..923b8de4a8696df470651d5d6c41c73eb33aaa98 100644
--- a/src/plugins/aorai/tests/ya/oracle/deterministic.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/deterministic.res.oracle
@@ -62,7 +62,7 @@ check lemma S0_deterministic_trans{L}:
        \at(aorai_CurOperation,L) ≡ op_real_main ∧
        \at(aorai_CurOpStatus,L) ≡ aorai_Called ∧ c ≡ 0);
  */
-/*@ ghost int aorai_CurStates = Si; */
+/*@ ghost enum aorai_States aorai_CurStates = Si; */
 /*@ ghost
   /@ requires aorai_CurStates ≡ S3;
      requires aorai_CurStates ≡ S3 ⇒ x ≡ 5 ∨ x ≡ 4;
@@ -116,14 +116,15 @@ check lemma S0_deterministic_trans{L}:
   void g_pre_func(int x)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_g;
-    if (3 == aorai_CurStates) {
+    if ((unsigned int)3 == aorai_CurStates) {
       if (x == 4) aorai_CurStates = S4; else goto __aorai_label;
     }
     else {
       __aorai_label: ;
-      if (3 == aorai_CurStates) 
+      if ((unsigned int)3 == aorai_CurStates) 
         if (x == 5) aorai_CurStates = S5;
         else aorai_CurStates = aorai_reject;
       else aorai_CurStates = aorai_reject;
@@ -185,11 +186,12 @@ check lemma S0_deterministic_trans{L}:
   void g_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_g;
-    if (5 == aorai_CurStates) aorai_CurStates = S1;
+    if ((unsigned int)5 == aorai_CurStates) aorai_CurStates = S1;
     else 
-      if (4 == aorai_CurStates) aorai_CurStates = S3;
+      if ((unsigned int)4 == aorai_CurStates) aorai_CurStates = S3;
       else aorai_CurStates = aorai_reject;
     return;
   }
@@ -263,9 +265,10 @@ void g(int x)
   void f_pre_func(int x)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_f;
-    if (1 == aorai_CurStates) 
+    if ((unsigned int)1 == aorai_CurStates) 
       if (x == 4) aorai_CurStates = S3; else aorai_CurStates = aorai_reject;
     else aorai_CurStates = aorai_reject;
     return;
@@ -321,9 +324,10 @@ void g(int x)
   void f_post_func(int res)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_f;
-    if (1 == aorai_CurStates) 
+    if ((unsigned int)1 == aorai_CurStates) 
       if (res == 0) 
         if (X == 5) aorai_CurStates = S2;
         else aorai_CurStates = aorai_reject;
@@ -407,14 +411,15 @@ int f(int x)
   void real_main_pre_func(int c)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_real_main;
-    if (0 == aorai_CurStates) {
+    if ((unsigned int)0 == aorai_CurStates) {
       if (c != 0) aorai_CurStates = S1; else goto __aorai_label_0;
     }
     else {
       __aorai_label_0: ;
-      if (0 == aorai_CurStates) 
+      if ((unsigned int)0 == aorai_CurStates) 
         if (c == 0) aorai_CurStates = S2;
         else aorai_CurStates = aorai_reject;
       else aorai_CurStates = aorai_reject;
@@ -471,9 +476,10 @@ int f(int x)
   void real_main_post_func(int res)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_real_main;
-    if (2 == aorai_CurStates) aorai_CurStates = Sf;
+    if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = Sf;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -543,9 +549,10 @@ int real_main(int c)
   void main_pre_func(int c)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
-    if (7 == aorai_CurStates) aorai_CurStates = S0;
+    if ((unsigned int)7 == aorai_CurStates) aorai_CurStates = S0;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -599,9 +606,10 @@ int real_main(int c)
   void main_post_func(int res)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
-    if (6 == aorai_CurStates) aorai_CurStates = Sf;
+    if ((unsigned int)6 == aorai_CurStates) aorai_CurStates = Sf;
     else aorai_CurStates = aorai_reject;
     return;
   }
diff --git a/src/plugins/aorai/tests/ya/oracle/floats.res.oracle b/src/plugins/aorai/tests/ya/oracle/floats.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..c813ffb28c36688e5a55a25d199070d18baa59e1
--- /dev/null
+++ b/src/plugins/aorai/tests/ya/oracle/floats.res.oracle
@@ -0,0 +1,487 @@
+[kernel] Parsing floats.i (no preprocessing)
+[kernel:parser:decimal-float] floats.i:8: Warning: 
+  Floating-point constant 0.001 is not represented exactly. Will use 0x1.0624dd2f1a9fcp-10.
+  (warn-once: no further messages from category 'parser:decimal-float' will be emitted)
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  aorai_CurOperation ∈ {op_square_root_aux}
+  aorai_CurOpStatus ∈ {aorai_Called}
+  aorai_CurStates ∈ {I}
+[eva:recursion] floats.i:11: 
+  detected recursive call of function square_root_aux.
+[eva] floats.i:11: Warning: 
+  Using specification of function square_root_aux for recursive calls.
+  Analysis of function square_root_aux is thus incomplete and its soundness
+  relies on the written specification.
+[eva] using specification for function square_root_aux
+[eva] floats.i:6: Warning: 
+  no \from part
+  for clause 'assigns aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;'
+[eva:alarm] :0: Warning: 
+  function square_root_aux, behavior Buchi_property_behavior: postcondition got status unknown.
+[eva:alarm] floats.i:11: Warning: 
+  non-finite float value.
+  assert \is_finite(tmp);
+  (tmp from square_root_aux(y, n))
+[eva] done for function main
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function main_post_func:
+  aorai_CurOperation ∈ {op_main}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {E}
+[eva:final-states] Values at end of function main_pre_func:
+  aorai_CurOperation ∈ {op_main}
+  aorai_CurOpStatus ∈ {aorai_Called}
+  aorai_CurStates ∈ {A}
+[eva:final-states] Values at end of function square_root_aux_post_func:
+  aorai_CurOperation ∈ {op_square_root_aux}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {B}
+[eva:final-states] Values at end of function square_root_aux_pre_func:
+  aorai_CurOperation ∈ {op_square_root_aux}
+  aorai_CurOpStatus ∈ {aorai_Called}
+  aorai_CurStates ∈ {B}
+[eva:final-states] Values at end of function square_root_post_func:
+  aorai_CurOperation ∈ {op_square_root}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {C}
+[eva:final-states] Values at end of function square_root_pre_func:
+  aorai_CurOperation ∈ {op_square_root}
+  aorai_CurOpStatus ∈ {aorai_Called}
+  aorai_CurStates ∈ {B}
+[eva:final-states] Values at end of function square_root_aux:
+  y ∈ {1.5}
+  __retres ∈ [-3.40282346639e+38 .. 3.40282346639e+38]
+  aorai_CurOperation ∈ {op_square_root_aux}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {B}
+[eva:final-states] Values at end of function square_root:
+  aorai_CurOperation ∈ {op_square_root}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {C}
+[eva:final-states] Values at end of function main:
+  r ∈ [-3.40282346639e+38 .. 3.40282346639e+38]
+  aorai_CurOperation ∈ {op_main}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {E}
+[eva:summary] ====== ANALYSIS SUMMARY ======
+  ----------------------------------------------------------------------------
+  9 functions analyzed (out of 9): 100% coverage.
+  In these functions, 53 statements reached (out of 67): 79% coverage.
+  ----------------------------------------------------------------------------
+  Some errors and warnings have been raised during the analysis:
+    by the Eva analyzer:      0 errors    2 warnings
+    by the Frama-C kernel:    0 errors    0 warnings
+  ----------------------------------------------------------------------------
+  1 alarm generated by the analysis:
+       1 nan or infinite floating-point value
+  ----------------------------------------------------------------------------
+  Evaluation of the logical properties reached by the analysis:
+    Assertions        0 valid     0 unknown     0 invalid      0 total
+    Preconditions    10 valid     2 unknown     0 invalid     12 total
+  83% of the logical properties reached have been proven.
+  ----------------------------------------------------------------------------
+[kernel] Parsing TMPDIR/aorai_floats_0.i (no preprocessing)
+/* Generated by Frama-C */
+enum aorai_States {
+    A = 0,
+    B = 1,
+    C = 2,
+    E = 3,
+    I = 4,
+    aorai_reject = 5
+};
+enum aorai_ListOper {
+    op_main = 2,
+    op_square_root = 1,
+    op_square_root_aux = 0
+};
+enum aorai_OpStatusList {
+    aorai_Terminated = 1,
+    aorai_Called = 0
+};
+/*@ check lemma aorai_reject_deterministic_trans{L}: \true;
+ */
+/*@ check lemma I_deterministic_trans{L}: \true;
+ */
+/*@ check lemma E_deterministic_trans{L}: \true;
+ */
+/*@ check lemma C_deterministic_trans{L}: \true;
+ */
+/*@ check lemma A_deterministic_trans{L}: \true;
+ */
+/*@ ghost enum aorai_ListOper aorai_CurOperation; */
+/*@ ghost enum aorai_OpStatusList aorai_CurOpStatus; */
+/*@
+check lemma B_deterministic_trans{L}:
+  (∀ float n, float x;
+     ¬(\at(aorai_CurOperation,L) ≡ op_square_root_aux ∧
+        \at(aorai_CurOpStatus,L) ≡ aorai_Terminated ∧
+        \at(aorai_CurOperation,L) ≡ op_square_root_aux ∧
+        \at(aorai_CurOpStatus,L) ≡ aorai_Called ∧ x ≥ 1.0f ∧ 
+        x ≤ n)) ∧
+  (∀ float n, float x;
+     ¬(\at(aorai_CurOperation,L) ≡ op_square_root ∧
+        \at(aorai_CurOpStatus,L) ≡ aorai_Terminated ∧
+        \at(aorai_CurOperation,L) ≡ op_square_root_aux ∧
+        \at(aorai_CurOpStatus,L) ≡ aorai_Called ∧ x ≥ 1.0f ∧ 
+        x ≤ n)) ∧
+  ¬(\at(aorai_CurOperation,L) ≡ op_square_root ∧
+     \at(aorai_CurOpStatus,L) ≡ aorai_Terminated ∧
+     \at(aorai_CurOperation,L) ≡ op_square_root_aux ∧
+     \at(aorai_CurOpStatus,L) ≡ aorai_Terminated);
+ */
+/*@ ghost enum aorai_States aorai_CurStates = I; */
+/*@ ghost
+  /@ requires aorai_CurStates ≡ B;
+     requires aorai_CurStates ≡ B ⇒ x ≥ 1.0f ∧ x ≤ n;
+     ensures aorai_CurOpStatus ≡ aorai_Called;
+     ensures aorai_CurOperation ≡ op_square_root_aux;
+     assigns aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     assigns aorai_CurOpStatus
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates, n, x;
+     assigns aorai_CurOperation
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates, n, x;
+     assigns aorai_CurStates
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates, n, x;
+     
+     behavior buch_state_A_out:
+       ensures aorai_CurStates ≢ A;
+     
+     behavior buch_state_B_in:
+       assumes aorai_CurStates ≡ B ∧ x ≥ 1.0f ∧ x ≤ n;
+       ensures aorai_CurStates ≡ B;
+     
+     behavior buch_state_B_out:
+       assumes aorai_CurStates ≢ B ∨ ¬(x ≥ 1.0f ∧ x ≤ n);
+       ensures aorai_CurStates ≢ B;
+     
+     behavior buch_state_C_out:
+       ensures aorai_CurStates ≢ C;
+     
+     behavior buch_state_E_out:
+       ensures aorai_CurStates ≢ E;
+     
+     behavior buch_state_I_out:
+       ensures aorai_CurStates ≢ I;
+     
+     behavior buch_state_aorai_reject_out:
+       ensures aorai_CurStates ≢ aorai_reject;
+   @/
+  void square_root_aux_pre_func(float x, float n)
+  {
+    /@ slevel full; @/
+    ;
+    aorai_CurOpStatus = aorai_Called;
+    aorai_CurOperation = op_square_root_aux;
+    if ((unsigned int)1 == aorai_CurStates) 
+      if (x >= 1.0f) 
+        if (x <= n) aorai_CurStates = B; else aorai_CurStates = aorai_reject;
+      else aorai_CurStates = aorai_reject;
+    else aorai_CurStates = aorai_reject;
+    return;
+  }
+
+*/
+
+/*@ ghost
+  /@ requires aorai_CurStates ≡ B;
+     ensures aorai_CurOpStatus ≡ aorai_Terminated;
+     ensures aorai_CurOperation ≡ op_square_root_aux;
+     assigns aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     assigns aorai_CurOpStatus
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     assigns aorai_CurOperation
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     assigns aorai_CurStates
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     
+     behavior buch_state_A_out:
+       ensures aorai_CurStates ≢ A;
+     
+     behavior buch_state_B_in:
+       assumes aorai_CurStates ≡ B;
+       ensures aorai_CurStates ≡ B;
+     
+     behavior buch_state_B_out:
+       assumes aorai_CurStates ≢ B;
+       ensures aorai_CurStates ≢ B;
+     
+     behavior buch_state_C_out:
+       ensures aorai_CurStates ≢ C;
+     
+     behavior buch_state_E_out:
+       ensures aorai_CurStates ≢ E;
+     
+     behavior buch_state_I_out:
+       ensures aorai_CurStates ≢ I;
+     
+     behavior buch_state_aorai_reject_out:
+       ensures aorai_CurStates ≢ aorai_reject;
+   @/
+  void square_root_aux_post_func(float res)
+  {
+    /@ slevel full; @/
+    ;
+    aorai_CurOpStatus = aorai_Terminated;
+    aorai_CurOperation = op_square_root_aux;
+    if ((unsigned int)1 == aorai_CurStates) aorai_CurStates = B;
+    else aorai_CurStates = aorai_reject;
+    return;
+  }
+
+*/
+
+/*@ requires aorai_CurStates ≡ B;
+    requires aorai_CurStates ≡ B ⇒ x ≥ 1.0f ∧ x ≤ n;
+    assigns \result, aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+    assigns \result \from x, n;
+    
+    behavior Buchi_property_behavior:
+      ensures aorai_CurStates ≡ B;
+ */
+float square_root_aux(float x, float n)
+{
+  float __retres;
+  /*@ ghost square_root_aux_pre_func(x,n); */
+  float y = (x + n / x) / 2.0f;
+  if ((double)(x - y) > 0.001) {
+    __retres = y;
+    goto return_label;
+  }
+  else {
+    float tmp;
+    tmp = square_root_aux(y,n);
+    /*@ assert Eva: is_nan_or_infinite: \is_finite(tmp); */ ;
+    __retres = tmp;
+    goto return_label;
+  }
+  return_label:
+  {
+    /*@ ghost square_root_aux_post_func(__retres); */
+    return __retres;
+  }
+}
+
+/*@ ghost
+  /@ requires aorai_CurStates ≡ A;
+     ensures aorai_CurOpStatus ≡ aorai_Called;
+     ensures aorai_CurOperation ≡ op_square_root;
+     assigns aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     assigns aorai_CurOpStatus
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     assigns aorai_CurOperation
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     assigns aorai_CurStates
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     
+     behavior buch_state_A_out:
+       ensures aorai_CurStates ≢ A;
+     
+     behavior buch_state_B_in:
+       assumes aorai_CurStates ≡ A;
+       ensures aorai_CurStates ≡ B;
+     
+     behavior buch_state_B_out:
+       assumes aorai_CurStates ≢ A;
+       ensures aorai_CurStates ≢ B;
+     
+     behavior buch_state_C_out:
+       ensures aorai_CurStates ≢ C;
+     
+     behavior buch_state_E_out:
+       ensures aorai_CurStates ≢ E;
+     
+     behavior buch_state_I_out:
+       ensures aorai_CurStates ≢ I;
+     
+     behavior buch_state_aorai_reject_out:
+       ensures aorai_CurStates ≢ aorai_reject;
+   @/
+  void square_root_pre_func(float n)
+  {
+    /@ slevel full; @/
+    ;
+    aorai_CurOpStatus = aorai_Called;
+    aorai_CurOperation = op_square_root;
+    if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = B;
+    else aorai_CurStates = aorai_reject;
+    return;
+  }
+
+*/
+
+/*@ ghost
+  /@ requires aorai_CurStates ≡ B;
+     ensures aorai_CurOpStatus ≡ aorai_Terminated;
+     ensures aorai_CurOperation ≡ op_square_root;
+     assigns aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     assigns aorai_CurOpStatus
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     assigns aorai_CurOperation
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     assigns aorai_CurStates
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     
+     behavior buch_state_A_out:
+       ensures aorai_CurStates ≢ A;
+     
+     behavior buch_state_B_out:
+       ensures aorai_CurStates ≢ B;
+     
+     behavior buch_state_C_in:
+       assumes aorai_CurStates ≡ B;
+       ensures aorai_CurStates ≡ C;
+     
+     behavior buch_state_C_out:
+       assumes aorai_CurStates ≢ B;
+       ensures aorai_CurStates ≢ C;
+     
+     behavior buch_state_E_out:
+       ensures aorai_CurStates ≢ E;
+     
+     behavior buch_state_I_out:
+       ensures aorai_CurStates ≢ I;
+     
+     behavior buch_state_aorai_reject_out:
+       ensures aorai_CurStates ≢ aorai_reject;
+   @/
+  void square_root_post_func(float res)
+  {
+    /@ slevel full; @/
+    ;
+    aorai_CurOpStatus = aorai_Terminated;
+    aorai_CurOperation = op_square_root;
+    if ((unsigned int)1 == aorai_CurStates) aorai_CurStates = C;
+    else aorai_CurStates = aorai_reject;
+    return;
+  }
+
+*/
+
+/*@ requires aorai_CurStates ≡ A;
+    
+    behavior Buchi_property_behavior:
+      ensures aorai_CurStates ≡ C;
+ */
+float square_root(float n)
+{
+  float tmp;
+  /*@ ghost square_root_pre_func(n); */
+  tmp = square_root_aux((float)1.0,n);
+  /*@ ghost square_root_post_func(tmp); */
+  return tmp;
+}
+
+/*@ ghost
+  /@ requires aorai_CurStates ≡ I;
+     ensures aorai_CurOpStatus ≡ aorai_Called;
+     ensures aorai_CurOperation ≡ op_main;
+     assigns aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     assigns aorai_CurOpStatus
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     assigns aorai_CurOperation
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     assigns aorai_CurStates
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     
+     behavior buch_state_A_in:
+       assumes aorai_CurStates ≡ I;
+       ensures aorai_CurStates ≡ A;
+     
+     behavior buch_state_A_out:
+       assumes aorai_CurStates ≢ I;
+       ensures aorai_CurStates ≢ A;
+     
+     behavior buch_state_B_out:
+       ensures aorai_CurStates ≢ B;
+     
+     behavior buch_state_C_out:
+       ensures aorai_CurStates ≢ C;
+     
+     behavior buch_state_E_out:
+       ensures aorai_CurStates ≢ E;
+     
+     behavior buch_state_I_out:
+       ensures aorai_CurStates ≢ I;
+     
+     behavior buch_state_aorai_reject_out:
+       ensures aorai_CurStates ≢ aorai_reject;
+   @/
+  void main_pre_func(void)
+  {
+    /@ slevel full; @/
+    ;
+    aorai_CurOpStatus = aorai_Called;
+    aorai_CurOperation = op_main;
+    if ((unsigned int)4 == aorai_CurStates) aorai_CurStates = A;
+    else aorai_CurStates = aorai_reject;
+    return;
+  }
+
+*/
+
+/*@ ghost
+  /@ requires aorai_CurStates ≡ C;
+     ensures aorai_CurOpStatus ≡ aorai_Terminated;
+     ensures aorai_CurOperation ≡ op_main;
+     assigns aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     assigns aorai_CurOpStatus
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     assigns aorai_CurOperation
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     assigns aorai_CurStates
+       \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;
+     
+     behavior buch_state_A_out:
+       ensures aorai_CurStates ≢ A;
+     
+     behavior buch_state_B_out:
+       ensures aorai_CurStates ≢ B;
+     
+     behavior buch_state_C_out:
+       ensures aorai_CurStates ≢ C;
+     
+     behavior buch_state_E_in:
+       assumes aorai_CurStates ≡ C;
+       ensures aorai_CurStates ≡ E;
+     
+     behavior buch_state_E_out:
+       assumes aorai_CurStates ≢ C;
+       ensures aorai_CurStates ≢ E;
+     
+     behavior buch_state_I_out:
+       ensures aorai_CurStates ≢ I;
+     
+     behavior buch_state_aorai_reject_out:
+       ensures aorai_CurStates ≢ aorai_reject;
+   @/
+  void main_post_func(void)
+  {
+    /@ slevel full; @/
+    ;
+    aorai_CurOpStatus = aorai_Terminated;
+    aorai_CurOperation = op_main;
+    if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = E;
+    else aorai_CurStates = aorai_reject;
+    return;
+  }
+
+*/
+
+/*@ requires aorai_CurStates ≡ I;
+    
+    behavior Buchi_property_behavior:
+      ensures aorai_CurStates ≡ E;
+ */
+void main(void)
+{
+  /*@ ghost main_pre_func(); */
+  float r = square_root(2.0f);
+  /*@ ghost main_post_func(); */
+  return;
+}
+
+
diff --git a/src/plugins/aorai/tests/ya/oracle/formals.res.oracle b/src/plugins/aorai/tests/ya/oracle/formals.res.oracle
index c37d669f42245f94696ce437ea63e1b5637551d2..3e76cd392c78a6744e7ab6e97911684a0353a815 100644
--- a/src/plugins/aorai/tests/ya/oracle/formals.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/formals.res.oracle
@@ -43,7 +43,7 @@ check lemma aorai_intermediate_state_0_deterministic_trans{L}:
      ¬(\at(aorai_CurOperation,L) ≡ op_g ∧
         \at(aorai_CurOpStatus,L) ≡ aorai_Called));
  */
-/*@ ghost int aorai_CurStates = init; */
+/*@ ghost enum aorai_States aorai_CurStates = init; */
 /*@ ghost int aorai_x_0 = 0; */
 /*@
 check lemma aorai_intermediate_state_2_deterministic_trans{L}:
@@ -139,9 +139,10 @@ check lemma aorai_intermediate_state_deterministic_trans{L}:
   void f_pre_func(int x)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_f;
-    if (7 == aorai_CurStates) {
+    if ((unsigned int)7 == aorai_CurStates) {
       if (x == 1) {
         aorai_CurStates = aorai_intermediate_state;
         aorai_x = x;
@@ -150,7 +151,7 @@ check lemma aorai_intermediate_state_deterministic_trans{L}:
     }
     else {
       __aorai_label: ;
-      if (7 == aorai_CurStates) 
+      if ((unsigned int)7 == aorai_CurStates) 
         if (x == 3) {
           aorai_CurStates = aorai_intermediate_state_2;
           aorai_x_0 = x;
@@ -238,26 +239,27 @@ check lemma aorai_intermediate_state_deterministic_trans{L}:
   void f_post_func(int res)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_f;
-    if (4 == aorai_CurStates) {
+    if ((unsigned int)4 == aorai_CurStates) {
       if (aorai_x_0 == 3) aorai_CurStates = OK; else goto __aorai_label_2;
     }
     else {
       __aorai_label_2: ;
-      if (1 == aorai_CurStates) {
+      if ((unsigned int)1 == aorai_CurStates) {
         if (aorai_x == 1) aorai_CurStates = aorai_intermediate_state_0;
         else goto __aorai_label_1;
       }
       else {
         __aorai_label_1: ;
-        if (4 == aorai_CurStates) {
+        if ((unsigned int)4 == aorai_CurStates) {
           if (aorai_x_0 != 3) aorai_CurStates = aorai_reject;
           else goto __aorai_label_0;
         }
         else {
           __aorai_label_0: ;
-          if (1 == aorai_CurStates) 
+          if ((unsigned int)1 == aorai_CurStates) 
             if (aorai_x != 1) aorai_CurStates = aorai_reject;
             else aorai_CurStates = aorai_reject;
           else aorai_CurStates = aorai_reject;
@@ -394,16 +396,17 @@ int f(int x)
   void g_pre_func(int y)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_g;
-    if (0 == aorai_CurStates) aorai_CurStates = OK;
+    if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = OK;
     else 
-      if (2 == aorai_CurStates) {
+      if ((unsigned int)2 == aorai_CurStates) {
         aorai_CurStates = aorai_intermediate_state_1;
         aorai_y = y;
       }
       else 
-        if (5 == aorai_CurStates) aorai_CurStates = aorai_reject;
+        if ((unsigned int)5 == aorai_CurStates) aorai_CurStates = aorai_reject;
         else aorai_CurStates = aorai_reject;
     return;
   }
@@ -474,18 +477,19 @@ int f(int x)
   void g_post_func(int res)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_g;
-    if (3 == aorai_CurStates) {
+    if ((unsigned int)3 == aorai_CurStates) {
       if (aorai_y == 2) aorai_CurStates = OK; else goto __aorai_label_3;
     }
     else {
       __aorai_label_3: ;
-      if (0 == aorai_CurStates) aorai_CurStates = OK;
+      if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = OK;
       else 
-        if (5 == aorai_CurStates) aorai_CurStates = aorai_reject;
+        if ((unsigned int)5 == aorai_CurStates) aorai_CurStates = aorai_reject;
         else 
-          if (3 == aorai_CurStates) 
+          if ((unsigned int)3 == aorai_CurStates) 
             if (aorai_y != 2) aorai_CurStates = aorai_reject;
             else aorai_CurStates = aorai_reject;
           else aorai_CurStates = aorai_reject;
@@ -575,9 +579,10 @@ int g(int y)
   void main_pre_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
-    if (6 == aorai_CurStates) aorai_CurStates = main_0;
+    if ((unsigned int)6 == aorai_CurStates) aorai_CurStates = main_0;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -633,11 +638,12 @@ int g(int y)
   void main_post_func(int res)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
-    if (0 == aorai_CurStates) aorai_CurStates = OK;
+    if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = OK;
     else 
-      if (5 == aorai_CurStates) aorai_CurStates = aorai_reject;
+      if ((unsigned int)5 == aorai_CurStates) aorai_CurStates = aorai_reject;
       else aorai_CurStates = aorai_reject;
     return;
   }
diff --git a/src/plugins/aorai/tests/ya/oracle/function_ptr.res.oracle b/src/plugins/aorai/tests/ya/oracle/function_ptr.res.oracle
index 16e5de830ac2b2f7e5c0161f7f79d538e4b30200..d3769b352d33da71077733114223d69059d67c7a 100644
--- a/src/plugins/aorai/tests/ya/oracle/function_ptr.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/function_ptr.res.oracle
@@ -65,7 +65,7 @@ check lemma aorai_intermediate_state_deterministic_trans{L}:
      ¬(\at(aorai_CurOperation,L) ≡ op_f ∧
         \at(aorai_CurOpStatus,L) ≡ aorai_Terminated));
  */
-/*@ ghost int aorai_CurStates = i; */
+/*@ ghost enum aorai_States aorai_CurStates = i; */
 /*@ ghost
   /@ requires aorai_CurStates ≡ g_called ∨ aorai_CurStates ≡ s1;
      ensures aorai_CurOpStatus ≡ aorai_Called;
@@ -121,11 +121,12 @@ check lemma aorai_intermediate_state_deterministic_trans{L}:
   void f_pre_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_f;
-    if (9 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state;
+    if ((unsigned int)9 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state;
     else 
-      if (6 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_2;
+      if ((unsigned int)6 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_2;
       else aorai_CurStates = aorai_reject;
     return;
   }
@@ -189,11 +190,12 @@ check lemma aorai_intermediate_state_deterministic_trans{L}:
   void f_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_f;
-    if (0 == aorai_CurStates) aorai_CurStates = f_called;
+    if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = f_called;
     else 
-      if (3 == aorai_CurStates) aorai_CurStates = ok;
+      if ((unsigned int)3 == aorai_CurStates) aorai_CurStates = ok;
       else aorai_CurStates = aorai_reject;
     return;
   }
@@ -275,11 +277,12 @@ void f(void)
   void g_pre_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_g;
-    if (9 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_0;
+    if ((unsigned int)9 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_0;
     else 
-      if (5 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_1;
+      if ((unsigned int)5 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_1;
       else aorai_CurStates = aorai_reject;
     return;
   }
@@ -343,11 +346,12 @@ void f(void)
   void g_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_g;
-    if (1 == aorai_CurStates) aorai_CurStates = g_called;
+    if ((unsigned int)1 == aorai_CurStates) aorai_CurStates = g_called;
     else 
-      if (2 == aorai_CurStates) aorai_CurStates = ok;
+      if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = ok;
       else aorai_CurStates = aorai_reject;
     return;
   }
@@ -424,9 +428,10 @@ void g(void)
   void main_pre_func(int c)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
-    if (7 == aorai_CurStates) aorai_CurStates = s1;
+    if ((unsigned int)7 == aorai_CurStates) aorai_CurStates = s1;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -483,9 +488,10 @@ void g(void)
   void main_post_func(int res)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
-    if (8 == aorai_CurStates) aorai_CurStates = ok;
+    if ((unsigned int)8 == aorai_CurStates) aorai_CurStates = ok;
     else aorai_CurStates = aorai_reject;
     return;
   }
diff --git a/src/plugins/aorai/tests/ya/oracle/generate_assigns_bts1290.res.oracle b/src/plugins/aorai/tests/ya/oracle/generate_assigns_bts1290.res.oracle
index 34366aa9fd40d3c26130b980494067d8a27b055a..2f0e7ce8e84ab43d8cba663cecc7766c1d3d8f73 100644
--- a/src/plugins/aorai/tests/ya/oracle/generate_assigns_bts1290.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/generate_assigns_bts1290.res.oracle
@@ -34,6 +34,7 @@ enum aorai_OpStatusList {
   {
     int S_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     S_tmp = S;
@@ -67,6 +68,7 @@ enum aorai_OpStatusList {
   {
     int S_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     S_tmp = S;
diff --git a/src/plugins/aorai/tests/ya/oracle/hoare_seq.res.oracle b/src/plugins/aorai/tests/ya/oracle/hoare_seq.res.oracle
index 0c22ea3ad2c717deed55f7fd804d2d8cf012610d..1a40c608459f2eabd9189ba8c1374eb87f5663b3 100644
--- a/src/plugins/aorai/tests/ya/oracle/hoare_seq.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/hoare_seq.res.oracle
@@ -116,6 +116,7 @@ enum aorai_OpStatusList {
     int aorai_intermediate_state_2_tmp;
     int aorai_reject_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_f;
     S0_tmp = S0;
@@ -244,6 +245,7 @@ enum aorai_OpStatusList {
     int aorai_intermediate_state_2_tmp;
     int aorai_reject_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_f;
     S0_tmp = S0;
@@ -440,6 +442,7 @@ int main_bhv_bhv(int c); */
     int aorai_intermediate_state_2_tmp;
     int aorai_reject_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     S0_tmp = S0;
@@ -584,6 +587,7 @@ int main_bhv_bhv(int c); */
     int aorai_intermediate_state_2_tmp;
     int aorai_reject_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     S0_tmp = S0;
diff --git a/src/plugins/aorai/tests/ya/oracle/incorrect.res.oracle b/src/plugins/aorai/tests/ya/oracle/incorrect.res.oracle
index e69f85f246c1dd25aac610260ab32ce16e9b29a4..4e77b2b2d82c624882c4cf7e1996d96a3a3a53f2 100644
--- a/src/plugins/aorai/tests/ya/oracle/incorrect.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/incorrect.res.oracle
@@ -22,7 +22,7 @@ int f(void);
 
 /*@ ghost enum aorai_ListOper aorai_CurOperation; */
 /*@ ghost enum aorai_OpStatusList aorai_CurOpStatus; */
-/*@ ghost int aorai_CurStates = s0; */
+/*@ ghost enum aorai_States aorai_CurStates = s0; */
 /*@ ghost
   /@ requires \false;
      ensures aorai_CurOpStatus ≡ aorai_Called;
@@ -44,6 +44,7 @@ int f(void);
   void main_pre_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     aorai_CurStates = aorai_reject;
@@ -73,6 +74,7 @@ int f(void);
   void main_post_func(int res)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     aorai_CurStates = aorai_reject;
diff --git a/src/plugins/aorai/tests/ya/oracle/logical_operators.res.oracle b/src/plugins/aorai/tests/ya/oracle/logical_operators.res.oracle
index 4aa48e2ee5d7fa37f6d81627004ac5e7f4955b9d..9257d2c5d17a1376ece0f36e6266d24c35657853 100644
--- a/src/plugins/aorai/tests/ya/oracle/logical_operators.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/logical_operators.res.oracle
@@ -36,6 +36,7 @@ enum aorai_OpStatusList {
   {
     int I_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_f;
     I_tmp = I;
@@ -77,6 +78,7 @@ enum aorai_OpStatusList {
   {
     int I_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_f;
     I_tmp = I;
@@ -124,6 +126,7 @@ void f(int x)
   {
     int I_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     I_tmp = I;
@@ -157,6 +160,7 @@ void f(int x)
   {
     int I_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     I_tmp = I;
diff --git a/src/plugins/aorai/tests/ya/oracle/loop_bts1050.res.oracle b/src/plugins/aorai/tests/ya/oracle/loop_bts1050.res.oracle
index 260cb460abb1c282a351d5544b232ff3f342f913..7d8927d391b2e483f1aacb22b9387b8794098d3c 100644
--- a/src/plugins/aorai/tests/ya/oracle/loop_bts1050.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/loop_bts1050.res.oracle
@@ -129,6 +129,7 @@ enum aorai_OpStatusList {
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_f;
     S0_tmp = S0;
@@ -259,6 +260,7 @@ enum aorai_OpStatusList {
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_f;
     S0_tmp = S0;
@@ -415,6 +417,7 @@ void f(void)
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_g;
     S0_tmp = S0;
@@ -538,6 +541,7 @@ void f(void)
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_g;
     S0_tmp = S0;
@@ -680,6 +684,7 @@ void g(void)
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     S0_tmp = S0;
@@ -804,6 +809,7 @@ void g(void)
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     S0_tmp = S0;
diff --git a/src/plugins/aorai/tests/ya/oracle/metavariables-right.res.oracle b/src/plugins/aorai/tests/ya/oracle/metavariables-right.res.oracle
index c09d670113547f3b377d5e31c0bee83e0959f4cf..67b68e9ab8ce82621e6b83f8ddc7066482f4d57c 100644
--- a/src/plugins/aorai/tests/ya/oracle/metavariables-right.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/metavariables-right.res.oracle
@@ -49,7 +49,7 @@ check lemma b_deterministic_trans{L}:
      \at(aorai_CurOperation,L) ≡ op_f ∧
      \at(aorai_CurOpStatus,L) ≡ aorai_Called);
  */
-/*@ ghost int aorai_CurStates = a; */
+/*@ ghost enum aorai_States aorai_CurStates = a; */
 /*@ ghost int aorai_x = 0; */
 /*@
 check lemma e_deterministic_trans{L}:
@@ -120,9 +120,10 @@ check lemma e_deterministic_trans{L}:
   void f_pre_func(int x)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_f;
-    if (2 == aorai_CurStates) {
+    if ((unsigned int)2 == aorai_CurStates) {
       aorai_CurStates = c;
       aorai_x = x;
       aorai_y = aorai_x;
@@ -183,9 +184,10 @@ check lemma e_deterministic_trans{L}:
   void f_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_f;
-    if (3 == aorai_CurStates) aorai_CurStates = e;
+    if ((unsigned int)3 == aorai_CurStates) aorai_CurStates = e;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -260,9 +262,10 @@ void f(int x)
   void g_pre_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_g;
-    if (2 == aorai_CurStates) aorai_CurStates = d;
+    if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = d;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -319,9 +322,10 @@ void f(int x)
   void g_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_g;
-    if (4 == aorai_CurStates) aorai_CurStates = g_0;
+    if ((unsigned int)4 == aorai_CurStates) aorai_CurStates = g_0;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -391,9 +395,10 @@ void g(void)
   void h_pre_func(int x)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_h;
-    if (5 == aorai_CurStates) 
+    if ((unsigned int)5 == aorai_CurStates) 
       if (aorai_x > 0) aorai_CurStates = f_0;
       else aorai_CurStates = aorai_reject;
     else aorai_CurStates = aorai_reject;
@@ -452,9 +457,10 @@ void g(void)
   void h_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_h;
-    if (6 == aorai_CurStates) aorai_CurStates = g_0;
+    if ((unsigned int)6 == aorai_CurStates) aorai_CurStates = g_0;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -524,9 +530,10 @@ void h(int x)
   void i_pre_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_i;
-    if (7 == aorai_CurStates) aorai_CurStates = h_0;
+    if ((unsigned int)7 == aorai_CurStates) aorai_CurStates = h_0;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -594,9 +601,10 @@ void h(int x)
   void i_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_i;
-    if (8 == aorai_CurStates) {
+    if ((unsigned int)8 == aorai_CurStates) {
       aorai_CurStates = e;
       aorai_y = 0;
       aorai_x = 1;
@@ -675,9 +683,10 @@ void i(void)
   void main_pre_func(int t)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
-    if (0 == aorai_CurStates) aorai_CurStates = b;
+    if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = b;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -734,9 +743,10 @@ void i(void)
   void main_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
-    if (5 == aorai_CurStates) aorai_CurStates = i_0;
+    if ((unsigned int)5 == aorai_CurStates) aorai_CurStates = i_0;
     else aorai_CurStates = aorai_reject;
     return;
   }
diff --git a/src/plugins/aorai/tests/ya/oracle/monostate.res.oracle b/src/plugins/aorai/tests/ya/oracle/monostate.res.oracle
index 925e912d1aedd0f75d769fd62f3649e84bad8447..eb4fbb3195124e602785ea9f55efa0161e20105b 100644
--- a/src/plugins/aorai/tests/ya/oracle/monostate.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/monostate.res.oracle
@@ -35,7 +35,7 @@ check lemma Init_deterministic_trans{L}:
      ¬(\at(aorai_CurOperation,L) ≡ op_main ∧
         \at(aorai_CurOpStatus,L) ≡ aorai_Called));
  */
-/*@ ghost int aorai_CurStates = Init; */
+/*@ ghost enum aorai_States aorai_CurStates = Init; */
 /*@ ghost
   /@ requires \false;
      ensures aorai_CurOpStatus ≡ aorai_Called;
@@ -69,11 +69,12 @@ check lemma Init_deterministic_trans{L}:
   void f_pre_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_f;
-    if (2 == aorai_CurStates) aorai_CurStates = aorai_reject;
+    if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = aorai_reject;
     else 
-      if (1 == aorai_CurStates) aorai_CurStates = aorai_reject;
+      if ((unsigned int)1 == aorai_CurStates) aorai_CurStates = aorai_reject;
       else aorai_CurStates = aorai_reject;
     return;
   }
@@ -109,9 +110,10 @@ check lemma Init_deterministic_trans{L}:
   void f_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_f;
-    if (2 == aorai_CurStates) aorai_CurStates = aorai_reject;
+    if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = aorai_reject;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -160,6 +162,7 @@ void f(void)
   void main_pre_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     aorai_CurStates = aorai_reject;
@@ -192,6 +195,7 @@ void f(void)
   void main_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     aorai_CurStates = aorai_reject;
diff --git a/src/plugins/aorai/tests/ya/oracle/not_prm.res.oracle b/src/plugins/aorai/tests/ya/oracle/not_prm.res.oracle
index 3caffe84fad47612be18e7e4c3fec7446a18c2c2..36fba5e9a2d04d52b622e0a3b0568d069c3e8b55 100644
--- a/src/plugins/aorai/tests/ya/oracle/not_prm.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/not_prm.res.oracle
@@ -41,6 +41,7 @@ enum aorai_OpStatusList {
     int S0_tmp;
     int Sf_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_f;
     S0_tmp = S0;
@@ -84,6 +85,7 @@ enum aorai_OpStatusList {
     int S0_tmp;
     int Sf_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_f;
     S0_tmp = S0;
diff --git a/src/plugins/aorai/tests/ya/oracle/observed.res.oracle b/src/plugins/aorai/tests/ya/oracle/observed.res.oracle
index e2e3a4fe94ea87191bbb7caa3162cf0bc7f927e5..05170397e238edc619affe696d5404119fa60430 100644
--- a/src/plugins/aorai/tests/ya/oracle/observed.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/observed.res.oracle
@@ -74,6 +74,7 @@ enum aorai_OpStatusList {
     int first_step_tmp;
     int init_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_f;
     aorai_intermediate_state_tmp = aorai_intermediate_state;
@@ -156,6 +157,7 @@ enum aorai_OpStatusList {
     int first_step_tmp;
     int init_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_f;
     aorai_intermediate_state_tmp = aorai_intermediate_state;
@@ -325,6 +327,7 @@ void g(void)
     int first_step_tmp;
     int init_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_h;
     aorai_intermediate_state_tmp = aorai_intermediate_state;
@@ -407,6 +410,7 @@ void g(void)
     int first_step_tmp;
     int init_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_h;
     aorai_intermediate_state_tmp = aorai_intermediate_state;
diff --git a/src/plugins/aorai/tests/ya/oracle/other.res.oracle b/src/plugins/aorai/tests/ya/oracle/other.res.oracle
index f83db815ae931852f8760e80e33016d64bfa76e4..7879583a70dd773cd54f39c03ff52d1251861310 100644
--- a/src/plugins/aorai/tests/ya/oracle/other.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/other.res.oracle
@@ -70,6 +70,7 @@ int x = 0;
     int last_tmp;
     int step1_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_f;
     init_tmp = init;
@@ -173,6 +174,7 @@ int x = 0;
     int last_tmp;
     int step1_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_f;
     init_tmp = init;
@@ -340,6 +342,7 @@ void f(void)
     int last_tmp;
     int step1_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_g;
     init_tmp = init;
@@ -443,6 +446,7 @@ void f(void)
     int last_tmp;
     int step1_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_g;
     init_tmp = init;
@@ -597,6 +601,7 @@ void g(void)
     int last_tmp;
     int step1_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     init_tmp = init;
@@ -671,6 +676,7 @@ void g(void)
     int last_tmp;
     int step1_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     init_tmp = init;
diff --git a/src/plugins/aorai/tests/ya/oracle/saveload.res.1.log.txt b/src/plugins/aorai/tests/ya/oracle/saveload.res.1.log.txt
index 7f7a57a4bac7e68a702ddc8dc1f4a1c8ae4bce31..58fd37adca9999eea9a8a09024059ced1f1c642d 100644
--- a/src/plugins/aorai/tests/ya/oracle/saveload.res.1.log.txt
+++ b/src/plugins/aorai/tests/ya/oracle/saveload.res.1.log.txt
@@ -4,37 +4,37 @@
 [eva] Computing initial state
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
-  aorai_CurOperation ∈ {0}
-  aorai_CurOpStatus ∈ {0}
-  aorai_CurStates ∈ {2}
+  aorai_CurOperation ∈ {op_main}
+  aorai_CurOpStatus ∈ {aorai_Called}
+  aorai_CurStates ∈ {init}
 [aorai] saveload.i:14: accept
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
 [eva:final-states] Values at end of function f_post_func:
-  aorai_CurOperation ∈ {1}
-  aorai_CurOpStatus ∈ {1}
-  aorai_CurStates ∈ {0}
+  aorai_CurOperation ∈ {op_f}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {accept}
 [eva:final-states] Values at end of function f_pre_func:
-  aorai_CurOperation ∈ {1}
-  aorai_CurOpStatus ∈ {0}
-  aorai_CurStates ∈ {0}
+  aorai_CurOperation ∈ {op_f}
+  aorai_CurOpStatus ∈ {aorai_Called}
+  aorai_CurStates ∈ {accept}
 [eva:final-states] Values at end of function f:
-  aorai_CurOperation ∈ {1}
-  aorai_CurOpStatus ∈ {1}
-  aorai_CurStates ∈ {0}
+  aorai_CurOperation ∈ {op_f}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {accept}
 [eva:final-states] Values at end of function main_post_func:
-  aorai_CurOperation ∈ {0}
-  aorai_CurOpStatus ∈ {1}
-  aorai_CurStates ∈ {0}
+  aorai_CurOperation ∈ {op_main}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {accept}
 [eva:final-states] Values at end of function main_pre_func:
-  aorai_CurOperation ∈ {0}
-  aorai_CurOpStatus ∈ {0}
-  aorai_CurStates ∈ {0}
+  aorai_CurOperation ∈ {op_main}
+  aorai_CurOpStatus ∈ {aorai_Called}
+  aorai_CurStates ∈ {accept}
 [eva:final-states] Values at end of function main:
   __retres ∈ {0}
-  aorai_CurOperation ∈ {0}
-  aorai_CurOpStatus ∈ {1}
-  aorai_CurStates ∈ {0}
+  aorai_CurOperation ∈ {op_main}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {accept}
 [eva:summary] ====== ANALYSIS SUMMARY ======
   ----------------------------------------------------------------------------
   6 functions analyzed (out of 6): 100% coverage.
diff --git a/src/plugins/aorai/tests/ya/oracle/seq.res.oracle b/src/plugins/aorai/tests/ya/oracle/seq.res.oracle
index b2f0a865f3d5c032ce7fbb3fca1f315091ada68d..4c0723689a86db3c32bfe5df30121f87991842ed 100644
--- a/src/plugins/aorai/tests/ya/oracle/seq.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/seq.res.oracle
@@ -114,6 +114,7 @@ enum aorai_OpStatusList {
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_f;
     S0_tmp = S0;
@@ -237,6 +238,7 @@ enum aorai_OpStatusList {
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_f;
     S0_tmp = S0;
@@ -406,6 +408,7 @@ void f(void)
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_g;
     S0_tmp = S0;
@@ -539,6 +542,7 @@ void f(void)
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_g;
     S0_tmp = S0;
@@ -705,6 +709,7 @@ void g(void)
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     S0_tmp = S0;
@@ -829,6 +834,7 @@ void g(void)
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     S0_tmp = S0;
diff --git a/src/plugins/aorai/tests/ya/oracle/seq_loop.res.oracle b/src/plugins/aorai/tests/ya/oracle/seq_loop.res.oracle
index bae62a6316898061fab0f135c5d8568de8d0e381..b256e59ddb8d0654c2d0c6a2a794045b9ac22c13 100644
--- a/src/plugins/aorai/tests/ya/oracle/seq_loop.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/seq_loop.res.oracle
@@ -129,6 +129,7 @@ enum aorai_OpStatusList {
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_f;
     S0_tmp = S0;
@@ -259,6 +260,7 @@ enum aorai_OpStatusList {
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_f;
     S0_tmp = S0;
@@ -415,6 +417,7 @@ void f(void)
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_g;
     S0_tmp = S0;
@@ -538,6 +541,7 @@ void f(void)
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_g;
     S0_tmp = S0;
@@ -680,6 +684,7 @@ void g(void)
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     S0_tmp = S0;
@@ -804,6 +809,7 @@ void g(void)
     int aorai_intermediate_state_2_tmp;
     int aorai_intermediate_state_3_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     S0_tmp = S0;
diff --git a/src/plugins/aorai/tests/ya/oracle/seq_unlimited.res.oracle b/src/plugins/aorai/tests/ya/oracle/seq_unlimited.res.oracle
index db603fa1ec63d19e7e6156d9048b95b17d41d13b..0b47507c6a2054e9e7352bfdce2a60e6174ba412 100644
--- a/src/plugins/aorai/tests/ya/oracle/seq_unlimited.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/seq_unlimited.res.oracle
@@ -48,7 +48,7 @@ check lemma aorai_intermediate_state_0_deterministic_trans{L}:
      \at(aorai_CurOperation,L) ≡ op_main ∧
      \at(aorai_CurOpStatus,L) ≡ aorai_Terminated);
  */
-/*@ ghost int aorai_CurStates = fst; */
+/*@ ghost enum aorai_States aorai_CurStates = fst; */
 /*@ ghost
   /@ requires aorai_CurStates ≡ b;
      ensures aorai_CurOpStatus ≡ aorai_Called;
@@ -93,9 +93,10 @@ check lemma aorai_intermediate_state_0_deterministic_trans{L}:
   void init_pre_func(int *a, int n)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_init;
-    if (4 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state;
+    if ((unsigned int)4 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -146,9 +147,10 @@ check lemma aorai_intermediate_state_0_deterministic_trans{L}:
   void init_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_init;
-    if (0 == aorai_CurStates) aorai_CurStates = c;
+    if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = c;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -235,11 +237,12 @@ void init(int *a, int n)
   void find_pre_func(int *a, int n, int k)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_find;
-    if (5 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_1;
+    if ((unsigned int)5 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_1;
     else 
-      if (1 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_1;
+      if ((unsigned int)1 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_1;
       else aorai_CurStates = aorai_reject;
     return;
   }
@@ -290,9 +293,10 @@ void init(int *a, int n)
   void find_post_func(int res)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_find;
-    if (2 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_0;
+    if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_0;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -394,9 +398,10 @@ int find(int *a, int n, int k)
   void main_pre_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
-    if (6 == aorai_CurStates) aorai_CurStates = b;
+    if ((unsigned int)6 == aorai_CurStates) aorai_CurStates = b;
     else aorai_CurStates = aorai_reject;
     return;
   }
@@ -447,9 +452,10 @@ int find(int *a, int n, int k)
   void main_post_func(int res)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
-    if (1 == aorai_CurStates) aorai_CurStates = ok;
+    if ((unsigned int)1 == aorai_CurStates) aorai_CurStates = ok;
     else aorai_CurStates = aorai_reject;
     return;
   }
diff --git a/src/plugins/aorai/tests/ya/oracle/serial.res.oracle b/src/plugins/aorai/tests/ya/oracle/serial.res.oracle
index f6cbbacc42cbecac9183de261ba17490eddb4cf3..843d3f17a658bb06d8c331b1b18d58f9c03ef5a7 100644
--- a/src/plugins/aorai/tests/ya/oracle/serial.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/serial.res.oracle
@@ -12,267 +12,125 @@
   aorai_x2 ∈ {0}
   aorai_y1 ∈ {0}
   aorai_y2 ∈ {0}
-  aorai_CurOperation ∈ {0}
-  aorai_CurOpStatus ∈ {0}
-  aorai_CurStates ∈ {19}
+  aorai_CurOperation ∈ {op_output}
+  aorai_CurOpStatus ∈ {aorai_Called}
+  aorai_CurStates ∈ {Wait1}
   aorai_StatesHistory_1 ∈ {19}
   aorai_StatesHistory_2 ∈ {19}
 [eva] using specification for function Frama_C_interval
 [eva] serial.c:58: starting to merge loop iterations
 [eva] serial.c:63: Trace partitioning superposing up to 100 states
-[eva] serial.c:63: Trace partitioning superposing up to 300 states
+[eva] serial.c:63: Trace partitioning superposing up to 200 states
 [eva:alarm] serial.c:33: Warning: 
   assertion 'Aorai,aorai_smoke_test' got status invalid (stopping propagation).
 [aorai] serial.c:92: Wait1 <- Wait1 <- Complete
-[aorai] serial.c:92: n in {5},x in [0..16383],y in [8192..16383]
-[aorai] serial.c:92: Wait1 <- Wait1 <- Complete
-[aorai] serial.c:92: n in {5},x in [0..16383],y in [0..8191]
-[eva] serial.c:63: Trace partitioning superposing up to 500 states
-[eva] serial.c:63: Trace partitioning superposing up to 700 states
+[aorai] serial.c:92: n in {5},x in [0..16383],y in [0..16383]
+[eva] serial.c:63: Trace partitioning superposing up to 400 states
+[eva] serial.c:63: Trace partitioning superposing up to 600 states
+[eva] serial.c:63: Trace partitioning superposing up to 800 states
 [eva] serial.c:63: Trace partitioning superposing up to 900 states
-[eva] serial.c:63: Trace partitioning superposing up to 1200 states
-[eva] serial.c:63: Trace partitioning superposing up to 1400 states
-[eva] serial.c:63: Trace partitioning superposing up to 1500 states
-[eva] serial.c:63: Trace partitioning superposing up to 1600 states
-[eva] serial.c:63: Trace partitioning superposing up to 1700 states
+[eva] serial.c:63: Trace partitioning superposing up to 1000 states
+[eva] serial.c:63: Trace partitioning superposing up to 1100 states
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
 [eva:final-states] Values at end of function input_data_post_func:
-  aorai_x1 ∈
-          {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18;
-           19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34;
-           35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50;
-           51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66;
-           67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82;
-           83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98;
-           99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111;
-           112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124;
-           125; 126; 127}
-  aorai_x2 ∈
-          {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18;
-           19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34;
-           35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50;
-           51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66;
-           67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82;
-           83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98;
-           99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111;
-           112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124;
-           125; 126; 127}
-  aorai_y1 ∈
-          {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18;
-           19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34;
-           35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50;
-           51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66;
-           67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82;
-           83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98;
-           99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111;
-           112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124;
-           125; 126; 127}
-  aorai_y2 ∈ [0..2147483647]
-  aorai_CurOperation ∈ {2}
-  aorai_CurOpStatus ∈ {1}
-  aorai_CurStates ∈ {0; 19; 20; 21; 22; 23}
+  aorai_x1 ∈ [0..127]
+  aorai_x2 ∈ [0..127]
+  aorai_y1 ∈ [0..127]
+  aorai_y2 ∈ [0..127]
+  aorai_CurOperation ∈ {op_input_data}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {Complete; Wait1; Wait2; Wait3; Wait4; Wait5}
   aorai_StatesHistory_1 ∈ {1; 2; 3; 4; 5; 6}
   aorai_StatesHistory_2 ∈ {8; 9; 10; 11; 12; 13}
 [eva:final-states] Values at end of function input_data_pre_func:
-  aorai_CurOperation ∈ {2}
-  aorai_CurOpStatus ∈ {0}
-  aorai_CurStates ∈ {1; 2; 3; 4; 5; 6}
+  aorai_CurOperation ∈ {op_input_data}
+  aorai_CurOpStatus ∈ {aorai_Called}
+  aorai_CurStates ∈
+                 {DataReq1; DataReq2; DataReq3; DataReq4; DataReq5; DataReqE}
   aorai_StatesHistory_1 ∈ {8; 9; 10; 11; 12; 13}
   aorai_StatesHistory_2 ∈ {14; 15; 16; 17; 18}
 [eva:final-states] Values at end of function input_data:
   Frama_C_entropy_source ∈ [--..--]
-  aorai_x1 ∈
-          {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18;
-           19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34;
-           35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50;
-           51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66;
-           67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82;
-           83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98;
-           99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111;
-           112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124;
-           125; 126; 127}
-  aorai_x2 ∈
-          {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18;
-           19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34;
-           35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50;
-           51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66;
-           67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82;
-           83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98;
-           99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111;
-           112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124;
-           125; 126; 127}
-  aorai_y1 ∈
-          {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18;
-           19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34;
-           35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50;
-           51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66;
-           67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82;
-           83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98;
-           99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111;
-           112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124;
-           125; 126; 127}
-  aorai_y2 ∈ [0..2147483647]
-  aorai_CurOperation ∈ {2}
-  aorai_CurOpStatus ∈ {1}
-  aorai_CurStates ∈ {0; 19; 20; 21; 22; 23}
+  aorai_x1 ∈ [0..127]
+  aorai_x2 ∈ [0..127]
+  aorai_y1 ∈ [0..127]
+  aorai_y2 ∈ [0..127]
+  aorai_CurOperation ∈ {op_input_data}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {Complete; Wait1; Wait2; Wait3; Wait4; Wait5}
   aorai_StatesHistory_1 ∈ {1; 2; 3; 4; 5; 6}
   aorai_StatesHistory_2 ∈ {8; 9; 10; 11; 12; 13}
 [eva:final-states] Values at end of function input_status_post_func:
-  aorai_CurOperation ∈ {1}
-  aorai_CurOpStatus ∈ {1}
-  aorai_CurStates ∈ {8; 9; 10; 11; 12; 13; 19; 20; 21; 22; 23}
+  aorai_CurOperation ∈ {op_input_status}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈
+                 {StatusError; StatusOk1; StatusOk2; StatusOk3; StatusOk4;
+                  StatusOk5; Wait1; Wait2; Wait3; Wait4; Wait5}
   aorai_StatesHistory_1 ∈ {14; 15; 16; 17; 18}
   aorai_StatesHistory_2 ∈ {0; 19; 20; 21; 22; 23}
 [eva:final-states] Values at end of function input_status_pre_func:
-  aorai_CurOperation ∈ {1}
-  aorai_CurOpStatus ∈ {0}
-  aorai_CurStates ∈ {14; 15; 16; 17; 18}
+  aorai_CurOperation ∈ {op_input_status}
+  aorai_CurOpStatus ∈ {aorai_Called}
+  aorai_CurStates ∈
+                 {StatusReq1; StatusReq2; StatusReq3; StatusReq4; StatusReq5}
   aorai_StatesHistory_1 ∈ {0; 19; 20; 21; 22; 23}
-  aorai_StatesHistory_2 ∈ {1; 2; 3; 4; 5; 6; 14; 15; 16; 17; 18; 19}
+  aorai_StatesHistory_2 ∈ [1..6] ∪ [14..19]
 [eva:final-states] Values at end of function input_status:
   Frama_C_entropy_source ∈ [--..--]
-  aorai_CurOperation ∈ {1}
-  aorai_CurOpStatus ∈ {1}
-  aorai_CurStates ∈ {8; 9; 10; 11; 12; 13; 19; 20; 21; 22; 23}
+  aorai_CurOperation ∈ {op_input_status}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈
+                 {StatusError; StatusOk1; StatusOk2; StatusOk3; StatusOk4;
+                  StatusOk5; Wait1; Wait2; Wait3; Wait4; Wait5}
   aorai_StatesHistory_1 ∈ {14; 15; 16; 17; 18}
   aorai_StatesHistory_2 ∈ {0; 19; 20; 21; 22; 23}
 [eva:final-states] Values at end of function output_post_func:
-  aorai_CurOperation ∈ {0}
-  aorai_CurOpStatus ∈ {1}
-  aorai_CurStates ∈ {19; 24}
+  aorai_CurOperation ∈ {op_output}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {Wait1; aorai_reject}
   aorai_StatesHistory_1 ∈ {7; 19}
   aorai_StatesHistory_2 ∈ {0}
 [eva:final-states] Values at end of function output_pre_func:
-  aorai_CurOperation ∈ {0}
-  aorai_CurOpStatus ∈ {0}
-  aorai_CurStates ∈ {7; 19; 24}
+  aorai_CurOperation ∈ {op_output}
+  aorai_CurOpStatus ∈ {aorai_Called}
+  aorai_CurStates ∈ {Error; Wait1; aorai_reject}
   aorai_StatesHistory_1 ∈ {0}
   aorai_StatesHistory_2 ∈ {5}
 [eva:final-states] Values at end of function output:
-  aorai_CurOperation ∈ {0}
-  aorai_CurOpStatus ∈ {1}
-  aorai_CurStates ∈ {19}
+  aorai_CurOperation ∈ {op_output}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {Wait1}
   aorai_StatesHistory_1 ∈ {19}
   aorai_StatesHistory_2 ∈ {0}
 [eva:final-states] Values at end of function read:
   Frama_C_entropy_source ∈ [--..--]
-  s ∈
-   {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; 19; 20;
-    21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; 35; 36; 37; 38;
-    39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50; 51; 52; 53; 54; 55; 56;
-    57; 58; 59; 60; 61; 62; 63; 64; 65; 66; 67; 68; 69; 70; 71; 72; 73; 74;
-    75; 76; 77; 78; 79; 80; 81; 82; 83; 84; 85; 86; 87; 88; 89; 90; 91; 92;
-    93; 94; 95; 96; 97; 98; 99; 100; 101; 102; 103; 104; 105; 106; 107; 108;
-    109; 110; 111; 112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122;
-    123; 124; 125; 126; 127; 128; 129; 130; 131; 132; 133; 134; 135; 136;
-    137; 138; 139; 140; 141; 142; 143; 144; 145; 146; 147; 148; 149; 150;
-    151; 152; 153; 154; 155; 156; 157; 158; 159; 160; 161; 162; 163; 164;
-    165; 166; 167; 168; 169; 170; 171; 172; 173; 174; 175; 176; 177; 178;
-    179; 180; 181; 182; 183; 184; 185; 186; 187; 188; 189; 190; 191; 192;
-    193; 194; 195; 196; 197; 198; 199; 200; 201; 202; 203; 204; 205; 206;
-    207; 208; 209; 210; 211; 212; 213; 214; 215; 216; 217; 218; 219; 220;
-    221; 222; 223; 224; 225; 226; 227; 228; 229; 230; 231; 232; 233; 234;
-    235; 236; 237; 238; 239; 240; 241; 242; 243; 244; 245; 246; 247; 248;
-    249; 250; 251; 252; 253; 254; 255}
+  s ∈ [0..255]
   status ∈ {0; 2; 4; 6; 8; 10; 12; 14} or UNINITIALIZED
   __retres ∈ [-1..255]
-  aorai_x1 ∈
-          {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18;
-           19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34;
-           35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50;
-           51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66;
-           67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82;
-           83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98;
-           99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111;
-           112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124;
-           125; 126; 127}
-  aorai_x2 ∈
-          {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18;
-           19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34;
-           35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50;
-           51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66;
-           67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82;
-           83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98;
-           99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111;
-           112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124;
-           125; 126; 127}
-  aorai_y1 ∈
-          {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18;
-           19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34;
-           35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50;
-           51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66;
-           67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82;
-           83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98;
-           99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111;
-           112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124;
-           125; 126; 127}
-  aorai_y2 ∈ [0..2147483647]
-  aorai_CurOperation ∈ {1; 2}
-  aorai_CurOpStatus ∈ {1}
-  aorai_CurStates ∈ {0; 19; 20; 21; 22; 23}
-  aorai_StatesHistory_1 ∈ {1; 2; 3; 4; 5; 6; 14; 15; 16; 17; 18}
-  aorai_StatesHistory_2 ∈ {0; 8; 9; 10; 11; 12; 13; 19; 20; 21; 22; 23}
+  aorai_x1 ∈ [0..127]
+  aorai_x2 ∈ [0..127]
+  aorai_y1 ∈ [0..127]
+  aorai_y2 ∈ [0..127]
+  aorai_CurOperation ∈ {op_input_status; op_input_data}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {Complete; Wait1; Wait2; Wait3; Wait4; Wait5}
+  aorai_StatesHistory_1 ∈ [1..6] ∪ [14..18]
+  aorai_StatesHistory_2 ∈ {0} ∪ [8..13] ∪ [19..23]
 [eva:final-states] Values at end of function main:
   Frama_C_entropy_source ∈ [--..--]
-  buffer[0] ∈
-        {0; 128; 129; 130; 131; 132; 133; 134; 135; 136; 137; 138; 139; 140;
-         141; 142; 143; 144; 145; 146; 147; 148; 149; 150; 151; 152; 153;
-         154; 155; 156; 157; 158; 159; 160; 161; 162; 163; 164; 165; 166;
-         167; 168; 169; 170; 171; 172; 173; 174; 175; 176; 177; 178; 179;
-         180; 181; 182; 183; 184; 185; 186; 187; 188; 189; 190; 191; 192;
-         193; 194; 195; 196; 197; 198; 199; 200; 201; 202; 203; 204; 205;
-         206; 207; 208; 209; 210; 211; 212; 213; 214; 215; 216; 217; 218;
-         219; 220; 221; 222; 223; 224; 225; 226; 227; 228; 229; 230; 231;
-         232; 233; 234; 235; 236; 237; 238; 239; 240; 241; 242; 243; 244;
-         245; 246; 247; 248; 249; 250; 251; 252; 253; 254; 255}
-        [1..2] ∈
-        {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18;
-         19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; 35;
-         36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50; 51; 52;
-         53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66; 67; 68; 69;
-         70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82; 83; 84; 85; 86;
-         87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98; 99; 100; 101; 102;
-         103; 104; 105; 106; 107; 108; 109; 110; 111; 112; 113; 114; 115;
-         116; 117; 118; 119; 120; 121; 122; 123; 124; 125; 126; 127}
-        [3..4] ∈ [0..2147483647]
+  buffer[0] ∈ {0} ∪ [128..255]
+        [1..4] ∈ [0..127]
   n ∈ {0; 1; 2; 3; 4}
-  aorai_x1 ∈
-          {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18;
-           19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34;
-           35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50;
-           51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66;
-           67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82;
-           83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98;
-           99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111;
-           112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124;
-           125; 126; 127}
-  aorai_x2 ∈
-          {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18;
-           19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34;
-           35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50;
-           51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66;
-           67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82;
-           83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98;
-           99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111;
-           112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124;
-           125; 126; 127}
-  aorai_y1 ∈
-          {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18;
-           19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34;
-           35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50;
-           51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66;
-           67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82;
-           83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98;
-           99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111;
-           112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124;
-           125; 126; 127}
-  aorai_y2 ∈ [0..2147483647]
-  aorai_CurOperation ∈ {0; 1; 2}
-  aorai_CurOpStatus ∈ {0; 1}
-  aorai_CurStates ∈ {0; 19; 20; 21; 22; 23}
-  aorai_StatesHistory_1 ∈ {1; 2; 3; 4; 5; 6; 14; 15; 16; 17; 18; 19}
-  aorai_StatesHistory_2 ∈ {0; 8; 9; 10; 11; 12; 13; 19; 20; 21; 22; 23}
+  aorai_x1 ∈ [0..127]
+  aorai_x2 ∈ [0..127]
+  aorai_y1 ∈ [0..127]
+  aorai_y2 ∈ [0..127]
+  aorai_CurOperation ∈ {op_output; op_input_status; op_input_data}
+  aorai_CurOpStatus ∈ {aorai_Called; aorai_Terminated}
+  aorai_CurStates ∈ {Complete; Wait1; Wait2; Wait3; Wait4; Wait5}
+  aorai_StatesHistory_1 ∈ [1..6] ∪ [14..19]
+  aorai_StatesHistory_2 ∈ {0} ∪ [8..13] ∪ [19..23]
 [eva:summary] ====== ANALYSIS SUMMARY ======
   ----------------------------------------------------------------------------
   11 functions analyzed (out of 11): 100% coverage.
@@ -344,7 +202,7 @@ int buffer[5];
 int n = 0;
 /*@ ghost enum aorai_ListOper aorai_CurOperation; */
 /*@ ghost enum aorai_OpStatusList aorai_CurOpStatus; */
-/*@ ghost int aorai_CurStates = Wait1; */
+/*@ ghost enum aorai_States aorai_CurStates = Wait1; */
 /*@ ghost int aorai_StatesHistory_1 = Wait1; */
 /*@ ghost int aorai_StatesHistory_2 = Wait1; */
 /*@ ghost int aorai_x1 = 0; */
@@ -355,33 +213,34 @@ int n = 0;
   void input_status_pre_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_input_status;
     aorai_StatesHistory_2 = aorai_StatesHistory_1;
-    aorai_StatesHistory_1 = aorai_CurStates;
-    if (19 == aorai_CurStates) aorai_CurStates = StatusReq1;
+    aorai_StatesHistory_1 = (int)aorai_CurStates;
+    if ((unsigned int)19 == aorai_CurStates) aorai_CurStates = StatusReq1;
     else 
-      if (9 == aorai_CurStates) aorai_CurStates = StatusReq1;
+      if ((unsigned int)9 == aorai_CurStates) aorai_CurStates = StatusReq1;
       else 
-        if (8 == aorai_CurStates) aorai_CurStates = StatusReq1;
+        if ((unsigned int)8 == aorai_CurStates) aorai_CurStates = StatusReq1;
         else 
-          if (0 == aorai_CurStates) aorai_CurStates = StatusReq1;
+          if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = StatusReq1;
           else 
-            if (20 == aorai_CurStates) aorai_CurStates = StatusReq2;
+            if ((unsigned int)20 == aorai_CurStates) aorai_CurStates = StatusReq2;
             else 
-              if (10 == aorai_CurStates) aorai_CurStates = StatusReq2;
+              if ((unsigned int)10 == aorai_CurStates) aorai_CurStates = StatusReq2;
               else 
-                if (21 == aorai_CurStates) aorai_CurStates = StatusReq3;
+                if ((unsigned int)21 == aorai_CurStates) aorai_CurStates = StatusReq3;
                 else 
-                  if (11 == aorai_CurStates) aorai_CurStates = StatusReq3;
+                  if ((unsigned int)11 == aorai_CurStates) aorai_CurStates = StatusReq3;
                   else 
-                    if (22 == aorai_CurStates) aorai_CurStates = StatusReq4;
+                    if ((unsigned int)22 == aorai_CurStates) aorai_CurStates = StatusReq4;
                     else 
-                      if (12 == aorai_CurStates) aorai_CurStates = StatusReq4;
+                      if ((unsigned int)12 == aorai_CurStates) aorai_CurStates = StatusReq4;
                       else 
-                        if (23 == aorai_CurStates) aorai_CurStates = StatusReq5;
+                        if ((unsigned int)23 == aorai_CurStates) aorai_CurStates = StatusReq5;
                         else 
-                          if (13 == aorai_CurStates) aorai_CurStates = StatusReq5;
+                          if ((unsigned int)13 == aorai_CurStates) aorai_CurStates = StatusReq5;
                           else aorai_CurStates = aorai_reject;
     /@ assert Aorai: aorai_smoke_test: aorai_CurStates ≢ aorai_reject; @/
     ;
@@ -394,111 +253,112 @@ int n = 0;
   void input_status_post_func(int res)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_input_status;
     aorai_StatesHistory_2 = aorai_StatesHistory_1;
-    aorai_StatesHistory_1 = aorai_CurStates;
-    if (18 == aorai_CurStates) {
-      if ((res & 15) != 1) {
-        if ((res & 1) != 0) aorai_CurStates = StatusError;
+    aorai_StatesHistory_1 = (int)aorai_CurStates;
+    if ((unsigned int)18 == aorai_CurStates) {
+      if ((res & 0b1111) != 1) {
+        if ((res & 0b0001) != 0) aorai_CurStates = StatusError;
         else goto __aorai_label_12;
       }
       else goto __aorai_label_12;
     }
     else {
       __aorai_label_12: ;
-      if (17 == aorai_CurStates) {
-        if ((res & 15) != 1) {
-          if ((res & 1) != 0) aorai_CurStates = StatusError;
+      if ((unsigned int)17 == aorai_CurStates) {
+        if ((res & 0b1111) != 1) {
+          if ((res & 0b0001) != 0) aorai_CurStates = StatusError;
           else goto __aorai_label_11;
         }
         else goto __aorai_label_11;
       }
       else {
         __aorai_label_11: ;
-        if (16 == aorai_CurStates) {
-          if ((res & 15) != 1) {
-            if ((res & 1) != 0) aorai_CurStates = StatusError;
+        if ((unsigned int)16 == aorai_CurStates) {
+          if ((res & 0b1111) != 1) {
+            if ((res & 0b0001) != 0) aorai_CurStates = StatusError;
             else goto __aorai_label_10;
           }
           else goto __aorai_label_10;
         }
         else {
           __aorai_label_10: ;
-          if (15 == aorai_CurStates) {
-            if ((res & 15) != 1) {
-              if ((res & 1) != 0) aorai_CurStates = StatusError;
+          if ((unsigned int)15 == aorai_CurStates) {
+            if ((res & 0b1111) != 1) {
+              if ((res & 0b0001) != 0) aorai_CurStates = StatusError;
               else goto __aorai_label_9;
             }
             else goto __aorai_label_9;
           }
           else {
             __aorai_label_9: ;
-            if (14 == aorai_CurStates) {
-              if ((res & 15) != 1) {
-                if ((res & 1) != 0) aorai_CurStates = StatusError;
+            if ((unsigned int)14 == aorai_CurStates) {
+              if ((res & 0b1111) != 1) {
+                if ((res & 0b0001) != 0) aorai_CurStates = StatusError;
                 else goto __aorai_label_8;
               }
               else goto __aorai_label_8;
             }
             else {
               __aorai_label_8: ;
-              if (14 == aorai_CurStates) {
-                if ((res & 15) == 1) aorai_CurStates = StatusOk1;
+              if ((unsigned int)14 == aorai_CurStates) {
+                if ((res & 0b1111) == 1) aorai_CurStates = StatusOk1;
                 else goto __aorai_label_7;
               }
               else {
                 __aorai_label_7: ;
-                if (15 == aorai_CurStates) {
-                  if ((res & 15) == 1) aorai_CurStates = StatusOk2;
+                if ((unsigned int)15 == aorai_CurStates) {
+                  if ((res & 0b1111) == 1) aorai_CurStates = StatusOk2;
                   else goto __aorai_label_6;
                 }
                 else {
                   __aorai_label_6: ;
-                  if (16 == aorai_CurStates) {
-                    if ((res & 15) == 1) aorai_CurStates = StatusOk3;
+                  if ((unsigned int)16 == aorai_CurStates) {
+                    if ((res & 0b1111) == 1) aorai_CurStates = StatusOk3;
                     else goto __aorai_label_5;
                   }
                   else {
                     __aorai_label_5: ;
-                    if (17 == aorai_CurStates) {
-                      if ((res & 15) == 1) aorai_CurStates = StatusOk4;
+                    if ((unsigned int)17 == aorai_CurStates) {
+                      if ((res & 0b1111) == 1) aorai_CurStates = StatusOk4;
                       else goto __aorai_label_4;
                     }
                     else {
                       __aorai_label_4: ;
-                      if (18 == aorai_CurStates) {
-                        if ((res & 15) == 1) aorai_CurStates = StatusOk5;
+                      if ((unsigned int)18 == aorai_CurStates) {
+                        if ((res & 0b1111) == 1) aorai_CurStates = StatusOk5;
                         else goto __aorai_label_3;
                       }
                       else {
                         __aorai_label_3: ;
-                        if (14 == aorai_CurStates) {
-                          if ((res & 1) == 0) aorai_CurStates = Wait1;
+                        if ((unsigned int)14 == aorai_CurStates) {
+                          if ((res & 0b0001) == 0) aorai_CurStates = Wait1;
                           else goto __aorai_label_2;
                         }
                         else {
                           __aorai_label_2: ;
-                          if (15 == aorai_CurStates) {
-                            if ((res & 1) == 0) aorai_CurStates = Wait2;
+                          if ((unsigned int)15 == aorai_CurStates) {
+                            if ((res & 0b0001) == 0) aorai_CurStates = Wait2;
                             else goto __aorai_label_1;
                           }
                           else {
                             __aorai_label_1: ;
-                            if (16 == aorai_CurStates) {
-                              if ((res & 1) == 0) aorai_CurStates = Wait3;
+                            if ((unsigned int)16 == aorai_CurStates) {
+                              if ((res & 0b0001) == 0) aorai_CurStates = Wait3;
                               else goto __aorai_label_0;
                             }
                             else {
                               __aorai_label_0: ;
-                              if (17 == aorai_CurStates) {
-                                if ((res & 1) == 0) aorai_CurStates = Wait4;
+                              if ((unsigned int)17 == aorai_CurStates) {
+                                if ((res & 0b0001) == 0) aorai_CurStates = Wait4;
                                 else goto __aorai_label;
                               }
                               else {
                                 __aorai_label: ;
-                                if (18 == aorai_CurStates) 
-                                  if ((res & 1) == 0) aorai_CurStates = Wait5;
+                                if ((unsigned int)18 == aorai_CurStates) 
+                                  if ((res & 0b0001) == 0) aorai_CurStates = Wait5;
                                   else aorai_CurStates = aorai_reject;
                                 else aorai_CurStates = aorai_reject;
                               }
@@ -540,31 +400,32 @@ int input_status(void)
   void input_data_pre_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_input_data;
     aorai_StatesHistory_2 = aorai_StatesHistory_1;
-    aorai_StatesHistory_1 = aorai_CurStates;
-    if (9 == aorai_CurStates) aorai_CurStates = DataReq1;
+    aorai_StatesHistory_1 = (int)aorai_CurStates;
+    if ((unsigned int)9 == aorai_CurStates) aorai_CurStates = DataReq1;
     else 
-      if (10 == aorai_CurStates) aorai_CurStates = DataReq2;
+      if ((unsigned int)10 == aorai_CurStates) aorai_CurStates = DataReq2;
       else 
-        if (11 == aorai_CurStates) aorai_CurStates = DataReq3;
+        if ((unsigned int)11 == aorai_CurStates) aorai_CurStates = DataReq3;
         else 
-          if (12 == aorai_CurStates) aorai_CurStates = DataReq4;
+          if ((unsigned int)12 == aorai_CurStates) aorai_CurStates = DataReq4;
           else 
-            if (13 == aorai_CurStates) aorai_CurStates = DataReq5;
+            if ((unsigned int)13 == aorai_CurStates) aorai_CurStates = DataReq5;
             else 
-              if (8 == aorai_CurStates) aorai_CurStates = DataReqE;
+              if ((unsigned int)8 == aorai_CurStates) aorai_CurStates = DataReqE;
               else 
-                if (23 == aorai_CurStates) aorai_CurStates = Error;
+                if ((unsigned int)23 == aorai_CurStates) aorai_CurStates = Error;
                 else 
-                  if (22 == aorai_CurStates) aorai_CurStates = Error;
+                  if ((unsigned int)22 == aorai_CurStates) aorai_CurStates = Error;
                   else 
-                    if (21 == aorai_CurStates) aorai_CurStates = Error;
+                    if ((unsigned int)21 == aorai_CurStates) aorai_CurStates = Error;
                     else 
-                      if (20 == aorai_CurStates) aorai_CurStates = Error;
+                      if ((unsigned int)20 == aorai_CurStates) aorai_CurStates = Error;
                       else 
-                        if (19 == aorai_CurStates) aorai_CurStates = Error;
+                        if ((unsigned int)19 == aorai_CurStates) aorai_CurStates = Error;
                         else aorai_CurStates = aorai_reject;
     /@ assert Aorai: aorai_smoke_test: aorai_CurStates ≢ aorai_reject; @/
     ;
@@ -577,12 +438,13 @@ int input_status(void)
   void input_data_post_func(int res)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_input_data;
     aorai_StatesHistory_2 = aorai_StatesHistory_1;
-    aorai_StatesHistory_1 = aorai_CurStates;
-    if (5 == aorai_CurStates) {
-      if ((res & 128) == 0) {
+    aorai_StatesHistory_1 = (int)aorai_CurStates;
+    if ((unsigned int)5 == aorai_CurStates) {
+      if ((res & 0b10000000) == 0b00000000) {
         aorai_CurStates = Complete;
         aorai_y2 = res;
       }
@@ -590,76 +452,76 @@ int input_status(void)
     }
     else 
       __aorai_label_26:
-      if (6 == aorai_CurStates) aorai_CurStates = Wait1;
+      if ((unsigned int)6 == aorai_CurStates) aorai_CurStates = Wait1;
       else 
-        if (5 == aorai_CurStates) {
-          if ((res & 192) == 192) aorai_CurStates = Wait1;
+        if ((unsigned int)5 == aorai_CurStates) {
+          if ((res & 0b11000000) == 0b11000000) aorai_CurStates = Wait1;
           else goto __aorai_label_25;
         }
         else {
           __aorai_label_25: ;
-          if (4 == aorai_CurStates) {
-            if ((res & 192) == 192) aorai_CurStates = Wait1;
+          if ((unsigned int)4 == aorai_CurStates) {
+            if ((res & 0b11000000) == 0b11000000) aorai_CurStates = Wait1;
             else goto __aorai_label_24;
           }
           else {
             __aorai_label_24: ;
-            if (3 == aorai_CurStates) {
-              if ((res & 192) == 192) aorai_CurStates = Wait1;
+            if ((unsigned int)3 == aorai_CurStates) {
+              if ((res & 0b11000000) == 0b11000000) aorai_CurStates = Wait1;
               else goto __aorai_label_23;
             }
             else {
               __aorai_label_23: ;
-              if (2 == aorai_CurStates) {
-                if ((res & 192) == 192) aorai_CurStates = Wait1;
+              if ((unsigned int)2 == aorai_CurStates) {
+                if ((res & 0b11000000) == 0b11000000) aorai_CurStates = Wait1;
                 else goto __aorai_label_22;
               }
               else {
                 __aorai_label_22: ;
-                if (1 == aorai_CurStates) {
-                  if ((res & 128) == 0) aorai_CurStates = Wait1;
+                if ((unsigned int)1 == aorai_CurStates) {
+                  if ((res & 0b10000000) == 0b00000000) aorai_CurStates = Wait1;
                   else goto __aorai_label_21;
                 }
                 else {
                   __aorai_label_21: ;
-                  if (1 == aorai_CurStates) {
-                    if ((res & 192) == 192) aorai_CurStates = Wait1;
+                  if ((unsigned int)1 == aorai_CurStates) {
+                    if ((res & 0b11000000) == 0b11000000) aorai_CurStates = Wait1;
                     else goto __aorai_label_20;
                   }
                   else {
                     __aorai_label_20: ;
-                    if (5 == aorai_CurStates) {
-                      if ((res & 192) == 128) aorai_CurStates = Wait2;
+                    if ((unsigned int)5 == aorai_CurStates) {
+                      if ((res & 0b11000000) == 0b10000000) aorai_CurStates = Wait2;
                       else goto __aorai_label_19;
                     }
                     else {
                       __aorai_label_19: ;
-                      if (4 == aorai_CurStates) {
-                        if ((res & 192) == 128) aorai_CurStates = Wait2;
+                      if ((unsigned int)4 == aorai_CurStates) {
+                        if ((res & 0b11000000) == 0b10000000) aorai_CurStates = Wait2;
                         else goto __aorai_label_18;
                       }
                       else {
                         __aorai_label_18: ;
-                        if (3 == aorai_CurStates) {
-                          if ((res & 192) == 128) aorai_CurStates = Wait2;
+                        if ((unsigned int)3 == aorai_CurStates) {
+                          if ((res & 0b11000000) == 0b10000000) aorai_CurStates = Wait2;
                           else goto __aorai_label_17;
                         }
                         else {
                           __aorai_label_17: ;
-                          if (2 == aorai_CurStates) {
-                            if ((res & 192) == 128) aorai_CurStates = Wait2;
+                          if ((unsigned int)2 == aorai_CurStates) {
+                            if ((res & 0b11000000) == 0b10000000) aorai_CurStates = Wait2;
                             else goto __aorai_label_16;
                           }
                           else {
                             __aorai_label_16: ;
-                            if (1 == aorai_CurStates) {
-                              if ((res & 192) == 128) aorai_CurStates = Wait2;
+                            if ((unsigned int)1 == aorai_CurStates) {
+                              if ((res & 0b11000000) == 0b10000000) aorai_CurStates = Wait2;
                               else goto __aorai_label_15;
                             }
                             else {
                               __aorai_label_15: ;
-                              if (2 == aorai_CurStates) {
-                                if ((res & 128) == 0) {
+                              if ((unsigned int)2 == aorai_CurStates) {
+                                if ((res & 0b10000000) == 0b00000000) {
                                   aorai_CurStates = Wait3;
                                   aorai_x1 = res;
                                 }
@@ -667,8 +529,8 @@ int input_status(void)
                               }
                               else {
                                 __aorai_label_14: ;
-                                if (3 == aorai_CurStates) {
-                                  if ((res & 128) == 0) {
+                                if ((unsigned int)3 == aorai_CurStates) {
+                                  if ((res & 0b10000000) == 0b00000000) {
                                     aorai_CurStates = Wait4;
                                     aorai_x2 = res;
                                   }
@@ -676,8 +538,8 @@ int input_status(void)
                                 }
                                 else {
                                   __aorai_label_13: ;
-                                  if (4 == aorai_CurStates) 
-                                    if ((res & 128) == 0) {
+                                  if ((unsigned int)4 == aorai_CurStates) 
+                                    if ((res & 0b10000000) == 0b00000000) {
                                       aorai_CurStates = Wait5;
                                       aorai_y1 = res;
                                     }
@@ -721,33 +583,34 @@ int input_data(void)
   void output_pre_func(int x, int y)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_output;
     aorai_StatesHistory_2 = aorai_StatesHistory_1;
-    aorai_StatesHistory_1 = aorai_CurStates;
-    if (23 == aorai_CurStates) aorai_CurStates = Error;
+    aorai_StatesHistory_1 = (int)aorai_CurStates;
+    if ((unsigned int)23 == aorai_CurStates) aorai_CurStates = Error;
     else 
-      if (22 == aorai_CurStates) aorai_CurStates = Error;
+      if ((unsigned int)22 == aorai_CurStates) aorai_CurStates = Error;
       else 
-        if (21 == aorai_CurStates) aorai_CurStates = Error;
+        if ((unsigned int)21 == aorai_CurStates) aorai_CurStates = Error;
         else 
-          if (20 == aorai_CurStates) aorai_CurStates = Error;
+          if ((unsigned int)20 == aorai_CurStates) aorai_CurStates = Error;
           else 
-            if (19 == aorai_CurStates) aorai_CurStates = Error;
+            if ((unsigned int)19 == aorai_CurStates) aorai_CurStates = Error;
             else 
-              if (13 == aorai_CurStates) aorai_CurStates = Error;
+              if ((unsigned int)13 == aorai_CurStates) aorai_CurStates = Error;
               else 
-                if (12 == aorai_CurStates) aorai_CurStates = Error;
+                if ((unsigned int)12 == aorai_CurStates) aorai_CurStates = Error;
                 else 
-                  if (11 == aorai_CurStates) aorai_CurStates = Error;
+                  if ((unsigned int)11 == aorai_CurStates) aorai_CurStates = Error;
                   else 
-                    if (10 == aorai_CurStates) aorai_CurStates = Error;
+                    if ((unsigned int)10 == aorai_CurStates) aorai_CurStates = Error;
                     else 
-                      if (9 == aorai_CurStates) aorai_CurStates = Error;
+                      if ((unsigned int)9 == aorai_CurStates) aorai_CurStates = Error;
                       else 
-                        if (8 == aorai_CurStates) aorai_CurStates = Error;
+                        if ((unsigned int)8 == aorai_CurStates) aorai_CurStates = Error;
                         else 
-                          if (0 == aorai_CurStates) {
+                          if ((unsigned int)0 == aorai_CurStates) {
                             if (y != aorai_y1 + 128 * aorai_y2) aorai_CurStates = Error;
                             else 
                               if (x != aorai_x1 + 128 * aorai_x2) aorai_CurStates = Error;
@@ -755,7 +618,7 @@ int input_data(void)
                           }
                           else {
                             __aorai_label_27: ;
-                            if (0 == aorai_CurStates) 
+                            if ((unsigned int)0 == aorai_CurStates) 
                               if (x == aorai_x1 + 128 * aorai_x2) 
                                 if (y == aorai_y1 + 128 * aorai_y2) aorai_CurStates = Wait1;
                                 else aorai_CurStates = aorai_reject;
@@ -773,11 +636,12 @@ int input_data(void)
   void output_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_output;
     aorai_StatesHistory_2 = aorai_StatesHistory_1;
-    aorai_StatesHistory_1 = aorai_CurStates;
-    if (19 == aorai_CurStates) aorai_CurStates = Wait1;
+    aorai_StatesHistory_1 = (int)aorai_CurStates;
+    if ((unsigned int)19 == aorai_CurStates) aorai_CurStates = Wait1;
     else aorai_CurStates = aorai_reject;
     /@ assert Aorai: aorai_smoke_test: aorai_CurStates ≢ aorai_reject; @/
     ;
@@ -827,11 +691,10 @@ void main(void)
           n = 0;
           continue;
         }
-      }
-      else {
         /*@ split data & 0x40; */ ;
-        if (n == 0) continue;
       }
+      else 
+        if (n == 0) continue;
       tmp_0 = n;
       n ++;
       buffer[tmp_0] = data;
diff --git a/src/plugins/aorai/tests/ya/oracle/single_call.res.oracle b/src/plugins/aorai/tests/ya/oracle/single_call.res.oracle
index 2b50360158fb85efec7991a9ae0405c2d4cf4af8..e59b671a435d7944dbe7c3aa9757b967206ebaad 100644
--- a/src/plugins/aorai/tests/ya/oracle/single_call.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/single_call.res.oracle
@@ -55,6 +55,7 @@ enum aorai_OpStatusList {
     int Sf_tmp;
     int aorai_intermediate_state_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     S0_tmp = S0;
@@ -114,6 +115,7 @@ enum aorai_OpStatusList {
     int Sf_tmp;
     int aorai_intermediate_state_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     S0_tmp = S0;
diff --git a/src/plugins/aorai/tests/ya/oracle/singleassignment-right.res.oracle b/src/plugins/aorai/tests/ya/oracle/singleassignment-right.res.oracle
index d717c70ab7b748be473e7a0955c84cfcc0b6db66..da7359cdf61dccd1fcf9f8ce3f6696cc4032efb4 100644
--- a/src/plugins/aorai/tests/ya/oracle/singleassignment-right.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/singleassignment-right.res.oracle
@@ -24,7 +24,7 @@ enum aorai_OpStatusList {
  */
 /*@ ghost enum aorai_ListOper aorai_CurOperation; */
 /*@ ghost enum aorai_OpStatusList aorai_CurOpStatus; */
-/*@ ghost int aorai_CurStates = a; */
+/*@ ghost enum aorai_States aorai_CurStates = a; */
 /*@ ghost int aorai_x = 0; */
 /*@ ghost int aorai_y = 0; */
 /*@ ghost
@@ -70,9 +70,10 @@ enum aorai_OpStatusList {
   void main_pre_func(int *x, int *y)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
-    if (0 == aorai_CurStates) {
+    if ((unsigned int)0 == aorai_CurStates) {
       aorai_CurStates = b;
       aorai_x = *x;
       aorai_y = *y;
@@ -126,9 +127,10 @@ enum aorai_OpStatusList {
   void main_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
-    if (2 == aorai_CurStates) {
+    if ((unsigned int)2 == aorai_CurStates) {
       aorai_CurStates = c;
       aorai_x = aorai_y;
       aorai_y = aorai_x;
diff --git a/src/plugins/aorai/tests/ya/oracle/stack.res.oracle b/src/plugins/aorai/tests/ya/oracle/stack.res.oracle
index cb79a5bd6d3f22ae4aa1fa8937b34a8114114863..4071686554d5628c250e63e0f5ae8ba494fb2903 100644
--- a/src/plugins/aorai/tests/ya/oracle/stack.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/stack.res.oracle
@@ -37,7 +37,7 @@ check lemma empty_stack_deterministic_trans{L}:
      \at(aorai_CurOperation,L) ≡ op_main ∧
      \at(aorai_CurOpStatus,L) ≡ aorai_Terminated);
  */
-/*@ ghost int aorai_CurStates = init; */
+/*@ ghost enum aorai_States aorai_CurStates = init; */
 /*@ ghost int aorai_n = 0; */
 /*@
 check lemma filled_stack_deterministic_trans{L}:
@@ -97,11 +97,12 @@ check lemma emptying_stack_deterministic_trans{L}:
   void push_pre_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_push;
-    if (4 == aorai_CurStates) aorai_CurStates = filling_stack;
+    if ((unsigned int)4 == aorai_CurStates) aorai_CurStates = filling_stack;
     else 
-      if (2 == aorai_CurStates) aorai_CurStates = filling_stack;
+      if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = filling_stack;
       else aorai_CurStates = aorai_reject;
     return;
   }
@@ -155,9 +156,10 @@ check lemma emptying_stack_deterministic_trans{L}:
   void push_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_push;
-    if (5 == aorai_CurStates) {
+    if ((unsigned int)5 == aorai_CurStates) {
       aorai_CurStates = filled_stack;
       aorai_n ++;
     }
@@ -235,9 +237,10 @@ void push(void)
   void pop_pre_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_pop;
-    if (4 == aorai_CurStates) 
+    if ((unsigned int)4 == aorai_CurStates) 
       if (aorai_n > 0) aorai_CurStates = emptying_stack;
       else aorai_CurStates = aorai_reject;
     else aorai_CurStates = aorai_reject;
@@ -301,9 +304,10 @@ void push(void)
   void pop_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_pop;
-    if (3 == aorai_CurStates) {
+    if ((unsigned int)3 == aorai_CurStates) {
       if (aorai_n == 1) {
         aorai_CurStates = empty_stack;
         aorai_n --;
@@ -312,7 +316,7 @@ void push(void)
     }
     else {
       __aorai_label: ;
-      if (3 == aorai_CurStates) 
+      if ((unsigned int)3 == aorai_CurStates) 
         if (aorai_n > 1) {
           aorai_CurStates = filled_stack;
           aorai_n --;
@@ -398,9 +402,10 @@ void pop(void)
   void main_pre_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
-    if (6 == aorai_CurStates) {
+    if ((unsigned int)6 == aorai_CurStates) {
       aorai_CurStates = empty_stack;
       aorai_n = 0;
     }
@@ -451,9 +456,10 @@ void pop(void)
   void main_post_func(void)
   {
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
-    if (2 == aorai_CurStates) aorai_CurStates = accept;
+    if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = accept;
     else aorai_CurStates = aorai_reject;
     return;
   }
diff --git a/src/plugins/aorai/tests/ya/oracle/test_acces_params.res.oracle b/src/plugins/aorai/tests/ya/oracle/test_acces_params.res.oracle
index c2fc72913e5f6c258e29064424942812828bf85e..e31ea6083264fd52bf1004dc3636195c6286f40f 100644
--- a/src/plugins/aorai/tests/ya/oracle/test_acces_params.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/test_acces_params.res.oracle
@@ -88,6 +88,7 @@ int rr = 1;
     int SF_tmp;
     int mainst_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_opa;
     S1_tmp = S1;
@@ -180,6 +181,7 @@ int rr = 1;
     int SF_tmp;
     int mainst_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_opa;
     S1_tmp = S1;
@@ -292,6 +294,7 @@ void opa(int i, int j)
     int SF_tmp;
     int mainst_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_opb;
     S1_tmp = S1;
@@ -383,6 +386,7 @@ void opa(int i, int j)
     int SF_tmp;
     int mainst_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_opb;
     S1_tmp = S1;
@@ -495,6 +499,7 @@ int opb(void)
     int SF_tmp;
     int mainst_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     S1_tmp = S1;
@@ -585,6 +590,7 @@ int opb(void)
     int SF_tmp;
     int mainst_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     S1_tmp = S1;
diff --git a/src/plugins/aorai/tests/ya/oracle/test_acces_params2.res.oracle b/src/plugins/aorai/tests/ya/oracle/test_acces_params2.res.oracle
index 59019d29de575c9d3c002abce06057b5d09f7361..6b1289c2a6d4bd4088ecc020cf530f9a0f6afbb1 100644
--- a/src/plugins/aorai/tests/ya/oracle/test_acces_params2.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/test_acces_params2.res.oracle
@@ -96,6 +96,7 @@ int rr = 1;
     int S6_tmp;
     int S7_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_opa;
     S1_tmp = S1;
@@ -199,6 +200,7 @@ int rr = 1;
     int S6_tmp;
     int S7_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_opa;
     S1_tmp = S1;
@@ -326,6 +328,7 @@ int opa(int r)
     int S6_tmp;
     int S7_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_opb;
     S1_tmp = S1;
@@ -426,6 +429,7 @@ int opa(int r)
     int S6_tmp;
     int S7_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_opb;
     S1_tmp = S1;
@@ -541,6 +545,7 @@ void opb(void)
     int S6_tmp;
     int S7_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_opc;
     S1_tmp = S1;
@@ -634,6 +639,7 @@ void opb(void)
     int S6_tmp;
     int S7_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_opc;
     S1_tmp = S1;
@@ -768,6 +774,7 @@ void opc(void)
     int S6_tmp;
     int S7_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     S1_tmp = S1;
@@ -868,6 +875,7 @@ void opc(void)
     int S6_tmp;
     int S7_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     S1_tmp = S1;
diff --git a/src/plugins/aorai/tests/ya/oracle/test_boucle_rechercheTableau.res.oracle b/src/plugins/aorai/tests/ya/oracle/test_boucle_rechercheTableau.res.oracle
index 1431fa716c3b4d91756d07526ea2c633f1174e1f..bc444e4bbcc155c9a6583fa490dc91905ea42ea4 100644
--- a/src/plugins/aorai/tests/ya/oracle/test_boucle_rechercheTableau.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/test_boucle_rechercheTableau.res.oracle
@@ -55,6 +55,7 @@ enum aorai_OpStatusList {
     int Idle_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_isPresent;
     End_tmp = End;
@@ -113,6 +114,7 @@ enum aorai_OpStatusList {
     int Idle_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_isPresent;
     End_tmp = End;
@@ -225,6 +227,7 @@ int isPresent(int *t, int max, int val)
     int Idle_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_foo;
     End_tmp = End;
@@ -277,6 +280,7 @@ int isPresent(int *t, int max, int val)
     int Idle_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_foo;
     End_tmp = End;
@@ -342,6 +346,7 @@ void foo(void)
     int Idle_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     End_tmp = End;
@@ -394,6 +399,7 @@ void foo(void)
     int Idle_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     End_tmp = End;
diff --git a/src/plugins/aorai/tests/ya/oracle/test_factorial.res.oracle b/src/plugins/aorai/tests/ya/oracle/test_factorial.res.oracle
index 56ba35bfc725a9e244a5be663abe9017446ccff9..429ca9bc1e86351a9db4ad2e0433457dd3de6063 100644
--- a/src/plugins/aorai/tests/ya/oracle/test_factorial.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/test_factorial.res.oracle
@@ -49,6 +49,7 @@ enum aorai_OpStatusList {
     int S2_tmp;
     int main_0_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_decode_int;
     S1_tmp = S1;
@@ -104,6 +105,7 @@ enum aorai_OpStatusList {
     int S2_tmp;
     int main_0_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_decode_int;
     S1_tmp = S1;
@@ -234,6 +236,7 @@ int decode_int(char *s)
     int S2_tmp;
     int main_0_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_factorial;
     S1_tmp = S1;
@@ -291,6 +294,7 @@ int decode_int(char *s)
     int S2_tmp;
     int main_0_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_factorial;
     S1_tmp = S1;
@@ -372,6 +376,7 @@ int factorial(int value)
     int S2_tmp;
     int main_0_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     S1_tmp = S1;
@@ -427,6 +432,7 @@ int factorial(int value)
     int S2_tmp;
     int main_0_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     S1_tmp = S1;
diff --git a/src/plugins/aorai/tests/ya/oracle/test_recursion4.res.oracle b/src/plugins/aorai/tests/ya/oracle/test_recursion4.res.oracle
index 8c9faad26773d78513719836e6856f9cfd4abbb8..58125fc6e68b3c1c0076f63159238ddf0660ea4e 100644
--- a/src/plugins/aorai/tests/ya/oracle/test_recursion4.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/test_recursion4.res.oracle
@@ -52,6 +52,7 @@ enum aorai_OpStatusList {
     int Idle_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_isPresent;
     End_tmp = End;
@@ -116,6 +117,7 @@ enum aorai_OpStatusList {
     int Idle_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_isPresent;
     End_tmp = End;
@@ -231,6 +233,7 @@ int isPresent(int *t, int size, int val)
     int Idle_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_foo;
     End_tmp = End;
@@ -283,6 +286,7 @@ int isPresent(int *t, int size, int val)
     int Idle_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_foo;
     End_tmp = End;
@@ -348,6 +352,7 @@ void foo(void)
     int Idle_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     End_tmp = End;
@@ -400,6 +405,7 @@ void foo(void)
     int Idle_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     End_tmp = End;
diff --git a/src/plugins/aorai/tests/ya/oracle/test_recursion5.res.oracle b/src/plugins/aorai/tests/ya/oracle/test_recursion5.res.oracle
index c7e017d08d504c11ddbf2c410794c4ab96b2c667..84601f1f62169f47d3e5cd4cebb7a384a421f840 100644
--- a/src/plugins/aorai/tests/ya/oracle/test_recursion5.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/test_recursion5.res.oracle
@@ -71,6 +71,7 @@ enum aorai_OpStatusList {
     int IgnoreFoo_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_isPresentRec;
     End_tmp = End;
@@ -154,6 +155,7 @@ enum aorai_OpStatusList {
     int IgnoreFoo_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_isPresentRec;
     End_tmp = End;
@@ -285,6 +287,7 @@ int isPresentRec(int *t, int i, int max, int val)
     int IgnoreFoo_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_isPresent;
     End_tmp = End;
@@ -361,6 +364,7 @@ int isPresentRec(int *t, int i, int max, int val)
     int IgnoreFoo_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_isPresent;
     End_tmp = End;
@@ -463,6 +467,7 @@ int isPresent(int *t, int max, int val)
     int IgnoreFoo_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_foo;
     End_tmp = End;
@@ -532,6 +537,7 @@ int isPresent(int *t, int max, int val)
     int IgnoreFoo_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_foo;
     End_tmp = End;
@@ -615,6 +621,7 @@ void foo(void)
     int IgnoreFoo_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     End_tmp = End;
@@ -684,6 +691,7 @@ void foo(void)
     int IgnoreFoo_tmp;
     int WillDoFoo_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     End_tmp = End;
diff --git a/src/plugins/aorai/tests/ya/oracle/test_struct.res.oracle b/src/plugins/aorai/tests/ya/oracle/test_struct.res.oracle
index 541b2c925a348a01a2ed36158f45f14207a5d55a..ecdc65fc67cbbff2acf74871a9420f36ed70efc1 100644
--- a/src/plugins/aorai/tests/ya/oracle/test_struct.res.oracle
+++ b/src/plugins/aorai/tests/ya/oracle/test_struct.res.oracle
@@ -50,6 +50,7 @@ int myAge = 0;
     int S1_tmp;
     int main_0_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_increment;
     S1_tmp = S1;
@@ -96,6 +97,7 @@ int myAge = 0;
     int S1_tmp;
     int main_0_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_increment;
     S1_tmp = S1;
@@ -159,6 +161,7 @@ void increment(void)
     int S1_tmp;
     int main_0_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Called;
     aorai_CurOperation = op_main;
     S1_tmp = S1;
@@ -205,6 +208,7 @@ void increment(void)
     int S1_tmp;
     int main_0_tmp;
     /@ slevel full; @/
+    ;
     aorai_CurOpStatus = aorai_Terminated;
     aorai_CurOperation = op_main;
     S1_tmp = S1;
diff --git a/src/plugins/aorai/tests/ya/oracle_prove/floats.res.oracle b/src/plugins/aorai/tests/ya/oracle_prove/floats.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..28b4a5aa18615ebfd8af4e80290b8e8385453f1c
--- /dev/null
+++ b/src/plugins/aorai/tests/ya/oracle_prove/floats.res.oracle
@@ -0,0 +1,87 @@
+[kernel] Parsing floats.i (no preprocessing)
+[kernel:parser:decimal-float] floats.i:8: Warning: 
+  Floating-point constant 0.001 is not represented exactly. Will use 0x1.0624dd2f1a9fcp-10.
+  (warn-once: no further messages from category 'parser:decimal-float' will be emitted)
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  aorai_CurOperation ∈ {op_square_root_aux}
+  aorai_CurOpStatus ∈ {aorai_Called}
+  aorai_CurStates ∈ {I}
+[eva:recursion] floats.i:11: 
+  detected recursive call of function square_root_aux.
+[eva] floats.i:11: Warning: 
+  Using specification of function square_root_aux for recursive calls.
+  Analysis of function square_root_aux is thus incomplete and its soundness
+  relies on the written specification.
+[eva] using specification for function square_root_aux
+[eva] floats.i:6: Warning: 
+  no \from part
+  for clause 'assigns aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;'
+[eva:alarm] :0: Warning: 
+  function square_root_aux, behavior Buchi_property_behavior: postcondition got status unknown.
+[eva:alarm] floats.i:11: Warning: 
+  non-finite float value.
+  assert \is_finite(tmp);
+  (tmp from square_root_aux(y, n))
+[eva] done for function main
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function main_post_func:
+  aorai_CurOperation ∈ {op_main}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {E}
+[eva:final-states] Values at end of function main_pre_func:
+  aorai_CurOperation ∈ {op_main}
+  aorai_CurOpStatus ∈ {aorai_Called}
+  aorai_CurStates ∈ {A}
+[eva:final-states] Values at end of function square_root_aux_post_func:
+  aorai_CurOperation ∈ {op_square_root_aux}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {B}
+[eva:final-states] Values at end of function square_root_aux_pre_func:
+  aorai_CurOperation ∈ {op_square_root_aux}
+  aorai_CurOpStatus ∈ {aorai_Called}
+  aorai_CurStates ∈ {B}
+[eva:final-states] Values at end of function square_root_post_func:
+  aorai_CurOperation ∈ {op_square_root}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {C}
+[eva:final-states] Values at end of function square_root_pre_func:
+  aorai_CurOperation ∈ {op_square_root}
+  aorai_CurOpStatus ∈ {aorai_Called}
+  aorai_CurStates ∈ {B}
+[eva:final-states] Values at end of function square_root_aux:
+  y ∈ {1.5}
+  __retres ∈ [-3.40282346639e+38 .. 3.40282346639e+38]
+  aorai_CurOperation ∈ {op_square_root_aux}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {B}
+[eva:final-states] Values at end of function square_root:
+  aorai_CurOperation ∈ {op_square_root}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {C}
+[eva:final-states] Values at end of function main:
+  r ∈ [-3.40282346639e+38 .. 3.40282346639e+38]
+  aorai_CurOperation ∈ {op_main}
+  aorai_CurOpStatus ∈ {aorai_Terminated}
+  aorai_CurStates ∈ {E}
+[eva:summary] ====== ANALYSIS SUMMARY ======
+  ----------------------------------------------------------------------------
+  9 functions analyzed (out of 9): 100% coverage.
+  In these functions, 53 statements reached (out of 67): 79% coverage.
+  ----------------------------------------------------------------------------
+  Some errors and warnings have been raised during the analysis:
+    by the Eva analyzer:      0 errors    2 warnings
+    by the Frama-C kernel:    0 errors    0 warnings
+  ----------------------------------------------------------------------------
+  1 alarm generated by the analysis:
+       1 nan or infinite floating-point value
+  ----------------------------------------------------------------------------
+  Evaluation of the logical properties reached by the analysis:
+    Assertions        0 valid     0 unknown     0 invalid      0 total
+    Preconditions    10 valid     2 unknown     0 invalid     12 total
+  83% of the logical properties reached have been proven.
+  ----------------------------------------------------------------------------
+[kernel] Parsing TMPDIR/aorai_floats_0_prove.i (no preprocessing)
+[wp] Warning: Missing RTE guards
diff --git a/src/plugins/aorai/tests/ya/serial.ya b/src/plugins/aorai/tests/ya/serial.ya
index 6e893819100f43bfb1a18da1cd6e2ecdfdf44bc7..adeff98b92d49c535e3f8588b31cfcaa14041f4b 100644
--- a/src/plugins/aorai/tests/ya/serial.ya
+++ b/src/plugins/aorai/tests/ya/serial.ya
@@ -9,6 +9,9 @@ $y2 : int;
 
 Error : { 0 == 1 } -> Error;
 
+/* In these states, the program is waiting for a status indicating that
+   data can be read */
+
 Wait1 :
   { CALL(input_status) } -> StatusReq1
 | { CALL(input_data) } -> Error
@@ -44,33 +47,35 @@ Wait5 :
 | other -> Wait5
 ;
 
+// The status have been requested, waiting for response
+
 StatusReq1 :
-  { input_status().\result & 1 == 0 } -> Wait1
-| { input_status().\result & 15 == 1 } -> StatusOk1
+  { input_status().\result & 0b0001 == 0 } -> Wait1
+| { input_status().\result & 0b1111 == 1 } -> StatusOk1
 | other -> StatusError
 ;
 
 StatusReq2 :
-  { input_status().\result & 1 == 0 } -> Wait2
-| { input_status().\result & 15 == 1 } -> StatusOk2
+  { input_status().\result & 0b0001 == 0 } -> Wait2
+| { input_status().\result & 0b1111 == 1 } -> StatusOk2
 | other -> StatusError
 ;
 
 StatusReq3 :
-  { input_status().\result & 1 == 0 } -> Wait3
-| { input_status().\result & 15 == 1 } -> StatusOk3
+  { input_status().\result & 0b0001 == 0 } -> Wait3
+| { input_status().\result & 0b1111 == 1 } -> StatusOk3
 | other -> StatusError
 ;
 
 StatusReq4 :
-  { input_status().\result & 1 == 0 } -> Wait4
-| { input_status().\result & 15 == 1 } -> StatusOk4
+  { input_status().\result & 0b0001 == 0 } -> Wait4
+| { input_status().\result & 0b1111 == 1 } -> StatusOk4
 | other -> StatusError
 ;
 
 StatusReq5 :
-  { input_status().\result & 1 == 0 } -> Wait5
-| { input_status().\result & 15 == 1 } -> StatusOk5
+  { input_status().\result & 0b0001 == 0 } -> Wait5
+| { input_status().\result & 0b1111 == 1 } -> StatusOk5
 | other -> StatusError
 ;
 
@@ -81,6 +86,8 @@ StatusError :
 | other -> StatusError
 ;
 
+// Ok status have been received, data can be read
+
 StatusOk1 :
   { CALL(input_status) } -> StatusReq1
 | { CALL(input_data) } -> DataReq1
@@ -116,40 +123,44 @@ StatusOk5 :
 | other -> StatusOk5
 ;
 
+// Data have been requested
+
 DataReqE :
   { RETURN(input_data) } -> Wait1
 ;
 
 DataReq1 :
-  { input_data().\result & 192 == 128 } -> Wait2
-| { input_data().\result & 192 == 192 } -> Wait1
-| { input_data().\result & 128 == 0 } -> Wait1
+  { input_data().\result & 0b11000000 == 0b10000000 } -> Wait2
+| { input_data().\result & 0b11000000 == 0b11000000 } -> Wait1
+| { input_data().\result & 0b10000000 == 0b00000000 } -> Wait1
 ;
 
 DataReq2 :
-  { input_data().\result & 192 == 128 } -> Wait2
-| { input_data().\result & 192 == 192 } -> Wait1
-| { input_data().\result & 128 == 0 } $x1 := \result; -> Wait3
+  { input_data().\result & 0b11000000 == 0b10000000 } -> Wait2
+| { input_data().\result & 0b11000000 == 0b11000000 } -> Wait1
+| { input_data().\result & 0b10000000 == 0b00000000 } $x1 := \result; -> Wait3
 ;
 
 DataReq3 :
-  { input_data().\result & 192 == 128 } -> Wait2
-| { input_data().\result & 192 == 192 } -> Wait1
-| { input_data().\result & 128 == 0 } $x2 := \result; -> Wait4
+  { input_data().\result & 0b11000000 == 0b10000000 } -> Wait2
+| { input_data().\result & 0b11000000 == 0b11000000 } -> Wait1
+| { input_data().\result & 0b10000000 == 0b00000000 } $x2 := \result; -> Wait4
 ;
 
 DataReq4 :
-  { input_data().\result & 192 == 128 } -> Wait2
-| { input_data().\result & 192 == 192 } -> Wait1
-| { input_data().\result & 128 == 0 } $y1 := \result; -> Wait5
+  { input_data().\result & 0b11000000 == 0b10000000 } -> Wait2
+| { input_data().\result & 0b11000000 == 0b11000000 } -> Wait1
+| { input_data().\result & 0b10000000 == 0b00000000 } $y1 := \result; -> Wait5
 ;
 
 DataReq5 :
-  { input_data().\result & 192 == 128 } -> Wait2
-| { input_data().\result & 192 == 192 } -> Wait1
-| { input_data().\result & 128 == 0 } $y2 := \result; -> Complete
+  { input_data().\result & 0b11000000 == 0b10000000 } -> Wait2
+| { input_data().\result & 0b11000000 == 0b11000000 } -> Wait1
+| { input_data().\result & 0b10000000 == 0b00000000 } $y2 := \result; -> Complete
 ;
 
+/* The sequence of 5 bytes read is complete */
+
 Complete :
   { CALL(output) && output().x == $x1 + 128 * $x2 && output().y == $y1 + 128 * $y2 } -> Wait1
 | { CALL(output) && (output().x != $x1 + 128 * $x2 || output().y != $y1 + 128 * $y2) } -> Error
diff --git a/src/plugins/aorai/utils_parser.ml b/src/plugins/aorai/utils_parser.ml
index d84bf49a1871ae97d520841f78fdfa7c19c3f0d8..e12815ab464a6ec87380121b1c7dbb4425a73680 100644
--- a/src/plugins/aorai/utils_parser.ml
+++ b/src/plugins/aorai/utils_parser.ml
@@ -43,3 +43,7 @@ let newline lexbuf =
   let pos = lexbuf.lex_curr_p in
   lexbuf.lex_curr_p <-
     { pos with pos_lnum = pos.pos_lnum + 1; pos_bol = pos.pos_cnum }
+
+let unterminated_comment lexbuf =
+  abort_current lexbuf
+    "Unterminated C comment"
diff --git a/src/plugins/aorai/utils_parser.mli b/src/plugins/aorai/utils_parser.mli
index 7b4b696bd7b8021e109f1607d4dccfed07bfd773..94495b62110040746c4b95118a696feec6cc7c6d 100644
--- a/src/plugins/aorai/utils_parser.mli
+++ b/src/plugins/aorai/utils_parser.mli
@@ -39,3 +39,6 @@ val unknown_token: Lexing.lexbuf -> 'a
 
 (** initiate a new line in the lexbuf *)
 val newline: Lexing.lexbuf -> unit
+
+(** aborts in case of an unterminated comment *)
+val unterminated_comment: Lexing.lexbuf -> 'a
diff --git a/src/plugins/aorai/yalexer.mll b/src/plugins/aorai/yalexer.mll
index 61042e3a8f6e71ddad87f078b1cd0a610dcc01b7..23ce704ca926df24cb7426e823638ffdf466d337 100644
--- a/src/plugins/aorai/yalexer.mll
+++ b/src/plugins/aorai/yalexer.mll
@@ -33,11 +33,54 @@ let alpha  = ['a'-'z' 'A'-'Z']
 let ident  = alpha (num | alpha | '_')*
 let string = ([^ '"' '\\']|'\\'_)*
 
+let decdigit = ['0'-'9']
+let octdigit = ['0'-'7']
+let hexdigit = ['0'-'9' 'a'-'f' 'A'-'F']
+let binarydigit = ['0' '1']
+let letter = ['a'- 'z' 'A'-'Z']
+
+let usuffix = ['u' 'U']
+let lsuffix = "l"|"L"|"ll"|"LL"
+let intsuffix =
+  lsuffix | usuffix | usuffix lsuffix | lsuffix usuffix
+| usuffix ? "i64"
+
+let hexprefix = '0' ['x' 'X']
+let binaryprefix = '0' ['b' 'B']
+
+let intnum = decdigit+ intsuffix?
+let octnum = '0' octdigit+ intsuffix?
+let hexnum = hexprefix hexdigit+ intsuffix?
+let binarynum = binaryprefix binarydigit+ intsuffix?
+
+let exponent = ['e' 'E']['+' '-']? decdigit+
+let fraction  = '.' decdigit+
+let decfloat =
+  (intnum? fraction)
+| (intnum exponent)
+| (intnum? fraction exponent)
+| (intnum '.')
+| (intnum '.' exponent)
+
+let hexfraction = hexdigit* '.' hexdigit+ | hexdigit+ '.'
+let binexponent = ['p' 'P'] ['+' '-']? decdigit+
+let hexfloat =
+  hexprefix hexfraction binexponent
+| hexprefix hexdigit+   binexponent
+
+let floatsuffix = ['f' 'F' 'l' 'L']
+let floatnum = (decfloat | hexfloat) floatsuffix?
 
 rule token = parse
     [' ' '\t' ]       { token lexbuf }     (* skip blanks *)
   | '\n'              { Utils_parser.newline lexbuf; token lexbuf }
-  | ['0'-'9']+ as lxm { INT(lxm) }
+  | "/*"              { comment lexbuf ; token lexbuf }
+  | "//"              { onelinecomment lexbuf ; token lexbuf }
+  | floatnum as lxm   { FLOAT(lxm) }
+  |	hexnum as lxm     { INT(lxm) }
+  |	octnum as lxm     { INT(lxm) }
+  | binarynum as lxm  { INT(lxm) }
+  |	intnum as lxm     { INT(lxm) }
   | "CALL"            { CALL_OF }
   | "RETURN"          { RETURN_OF }
   | "COR"             { CALLORRETURN_OF }
@@ -82,3 +125,12 @@ rule token = parse
   | eof               { EOF }
   | ":="              { AFF }
   | _                 { Utils_parser.unknown_token lexbuf }
+
+and comment = parse
+  |  "*/"       {  }
+  | eof         { Utils_parser.unterminated_comment lexbuf }
+  | _           { comment lexbuf }
+
+and onelinecomment = parse
+  | '\n'|eof    {  }
+  | _           { onelinecomment lexbuf }
diff --git a/src/plugins/aorai/yaparser.mly b/src/plugins/aorai/yaparser.mly
index f900b6350c7783a4a1c2ccbcaf14e522033a5af4..1fbcaa6d72eecd249324feb7a4adc898e44e5b9f 100644
--- a/src/plugins/aorai/yaparser.mly
+++ b/src/plugins/aorai/yaparser.mly
@@ -154,6 +154,7 @@ type pre_cond = Behavior of string | Pre of Automaton_ast.condition
 %token <string> IDENTIFIER
 %token <string> METAVAR
 %token <string> INT
+%token <string> FLOAT
 %token AFF
 %token LCURLY RCURLY LPAREN RPAREN LSQUARE RSQUARE LBRACELBRACE RBRACERBRACE
 %token RARROW
@@ -388,7 +389,9 @@ arith_relation_bw
 /* returns a Lval exp or a Const exp*/
 access_or_const
   : INT { PCst (IntConstant $1) }
+  | FLOAT { PCst (FloatConstant $1) }
   | MINUS INT { PUnop (Uminus, PCst (IntConstant $2)) }
+  | MINUS FLOAT { PUnop (Uminus, PCst (FloatConstant $2)) }
   | access { $1 }
   ;
 
diff --git a/src/plugins/callgraph/callgraph_api.ml b/src/plugins/callgraph/callgraph_api.ml
index 712ccd11aed0a5ecd49c658f5e3973f8574bcb6b..8ae2e7c7fca02cb0f65f6ff832b96ecad84799a3 100644
--- a/src/plugins/callgraph/callgraph_api.ml
+++ b/src/plugins/callgraph/callgraph_api.ml
@@ -43,6 +43,9 @@ module type Graph = sig
   val is_computed: unit -> bool
   (** Is the graph already built? *)
 
+  val add_hook: (G.t -> unit) -> unit
+  (** Call registered hook each time the graph is computed *)
+
   val self: State.t
 
 end
@@ -60,7 +63,6 @@ module type Services = sig
 
   val entry_point: unit -> G.V.t option
   val is_root: Kernel_function.t -> bool
-
 end
 
 (*
diff --git a/src/plugins/callgraph/cg.ml b/src/plugins/callgraph/cg.ml
index 24c12d9a2ea69474d83e03035708ec5161c69154..1d0816867404ecbe6f0b4d0135e33702d3e57f56 100644
--- a/src/plugins/callgraph/cg.ml
+++ b/src/plugins/callgraph/cg.ml
@@ -66,8 +66,11 @@ module State =
       let dependencies = [ Eva.Analysis.self; Globals.Functions.self ]
     end)
 
+module StateHook = Hook.Build (D)
+
 let self = State.self
 let is_computed () = State.is_computed ()
+let add_hook = StateHook.extend
 
 (** @return the list of functions which address is taken.*)
 let get_pointed_kfs =
@@ -101,7 +104,6 @@ let get_pointed_kfs =
     match !res with
     | None ->
       let l = compute () in
-      State.mark_as_computed ();
       res := Some l;
       l
     | Some l -> l
@@ -232,6 +234,8 @@ let compute () =
     semantic_compute g
   end else
     (if Eva.Analysis.is_computed () then semantic_compute else syntactic_compute) g;
+  State.mark_as_computed ();
+  StateHook.apply g;
   g
 
 let get () = State.memo compute
diff --git a/src/plugins/callgraph/requests.ml b/src/plugins/callgraph/requests.ml
new file mode 100644
index 0000000000000000000000000000000000000000..cdef7f503d12adab16126d22d094cecf24057518
--- /dev/null
+++ b/src/plugins/callgraph/requests.ml
@@ -0,0 +1,179 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2023                                               *)
+(*    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 Server
+
+module G = Services.G
+
+(* --- Package declaration --- *)
+
+let package = Package.package ~plugin:"callgraph" ~title:"Callgraph" ()
+
+
+(* --- Helper modules --- *)
+
+module Record () =
+struct
+  module Record = Data.Record
+  type record
+  let record : record Record.signature = Record.signature ()
+  let field name ?(descr = name) =
+    Record.field record ~name ~descr:(Markdown.plain descr)
+  let publish ?descr name =
+    let descr = Option.map Markdown.plain descr in
+    Record.publish record ~package ~name ?descr
+end
+
+module Enum (X: sig type t end) =
+struct
+  module Enum = Data.Enum
+  let dictionary: X.t Enum.dictionary = Enum.dictionary ()
+  let tag name descr = Enum.tag ~name ~descr:(Markdown.plain descr) dictionary
+  let publish lookup name descr =
+    Enum.set_lookup dictionary lookup;
+    Request.dictionary ~package ~name ~descr:(Markdown.plain descr) dictionary
+end
+
+
+(* --- Types --- *)
+
+module Vertex =
+struct
+  include Record ()
+
+  let kf = field "kf" (module Kernel_ast.Function)
+      ~descr: "The function represented by the node"
+  let is_root = field "is_root" Data.jbool
+      ~descr: "whether this node is the root of a service"
+  let root = field "root" (module Kernel_ast.Function)
+      ~descr: "the root of this node's service"
+
+  include (val publish "vertex")
+  type t = Cil_types.kernel_function Service_graph.vertex
+
+  let to_json (v : Cil_types.kernel_function Service_graph.vertex) =
+    default |>
+    set kf v.node |>
+    set is_root v.is_root |>
+    set root v.root.node |>
+    to_json
+
+  let of_json _js = Data.failure "Vertex.of_json not implemented"
+end
+
+module EdgeKind =
+struct
+  include Enum (struct type t = Service_graph.edge end)
+
+  let inter_services =  tag "inter_services" "a call between two services"
+  let inter_functions = tag "inter_functions" "a call inside a service"
+  let both =            tag "both" "both cases above"
+
+  let lookup = function
+    | Service_graph.Inter_services -> inter_services
+    | Inter_functions -> inter_functions
+    | Both -> both
+
+  include (val publish lookup
+              "edgeKind" "Whether the call goes through services or not")
+end
+
+module Edge =
+struct
+  include Record ()
+
+  let src = field "src" (module Kernel_ast.Function)
+  let dst = field "dst" (module Kernel_ast.Function)
+  let kind = field "kind" (module EdgeKind)
+
+  include (val publish "edge")
+  type t = G.E.t
+
+  let to_json (e : t) =
+    default |>
+    set src (G.E.src e).node |>
+    set dst (G.E.dst e).node |>
+    set kind (G.E.label e) |>
+    to_json
+
+  let of_json _js = Data.failure "Edge.of_json not implemented"
+end
+
+module Graph =
+struct
+  include Record ()
+
+  let vertices = field "vertices" (module Data.Jlist (Vertex))
+  let edges = field "edges" (module Data.Jlist (Edge))
+
+  include (val publish "graph" ~descr:"The callgraph of the current project")
+  type t = G.t
+
+  let get_vertices (g : t) =
+    G.fold_vertex (fun v acc -> v :: acc ) g []
+
+  let get_edges (g : t) =
+    G.fold_edges_e (fun v acc -> v :: acc ) g []
+
+  let to_json (g : t) =
+    default |>
+    set vertices (get_vertices g) |>
+    set edges (get_edges g) |>
+    to_json
+
+  let of_json _js = Data.failure "Graph.of_json not implemented"
+end
+
+
+(* --- Requests --- *)
+
+let _signal =
+  States.register_value
+    ~package ~name:"callgraph"
+    ~descr:(Markdown.plain
+              "The current callgraph or an empty graph if it has not been computed yet")
+    ~output:(module Data.Joption (Graph))
+    ~add_hook:Services.add_hook
+    ~get:
+      begin fun () ->
+        if Services.is_computed () then
+          Some (Services.get ())
+        else
+          None
+      end
+    ()
+
+let _signal =
+  States.register_value
+    ~package ~name:"isComputed"
+    ~descr:(Markdown.plain
+              "This boolean is true if the graph has been computed")
+    ~output:(module Data.Jbool)
+    ~add_hook:Services.add_hook
+    ~get:Services.is_computed
+    ()
+
+let () = Request.register ~package
+    ~kind:`EXEC ~name:"compute"
+    ~descr:(Markdown.plain "Compute the callgraph for the current project")
+    ~input:(module Data.Junit) ~output:(module Data.Junit)
+    (fun () -> ignore (Services.get ()))
diff --git a/src/plugins/gui/debug_manager.ko.ml b/src/plugins/callgraph/requests.mli
similarity index 95%
rename from src/plugins/gui/debug_manager.ko.ml
rename to src/plugins/callgraph/requests.mli
index 14207880c6263d2e85a2992f62c80dd8cc23cd2e..d68abd32119990046a8bed6a36cfb5e6c3b8c264 100644
--- a/src/plugins/gui/debug_manager.ko.ml
+++ b/src/plugins/callgraph/requests.mli
@@ -20,4 +20,4 @@
 (*                                                                        *)
 (**************************************************************************)
 
-(* empty file *)
+(* This module only register requests for Frama-C Server. Nothing is exported *)
diff --git a/src/plugins/callgraph/services.ml b/src/plugins/callgraph/services.ml
index b2d3f2893fbb6f37313b3472a20777c936386867..1345b6fcdf985cdd78322a2a91fa205a253dc58f 100644
--- a/src/plugins/callgraph/services.ml
+++ b/src/plugins/callgraph/services.ml
@@ -77,9 +77,12 @@ module State =
       let dependencies = [ Cg.self; Kernel.MainFunction.self ]
     end)
 
+module StateHook = Hook.Build (S.Service_graph.Datatype)
+
 (* eta-expansion required to mask optional argument [?project] *)
 let is_computed () = State.is_computed ()
 let self = State.self
+let add_hook = StateHook.extend
 
 let compute () =
   let cg = Cg.get () in
@@ -92,6 +95,7 @@ let compute () =
   in
   let sg = S.compute cg isr_names in
   State.mark_as_computed ();
+  StateHook.apply sg;
   sg
 
 let get () = State.memo compute
diff --git a/src/plugins/dive/build.ml b/src/plugins/dive/build.ml
index 6116da7e18d2b5b186d55d1727ba695d59240969..acfa92afaa6498c25af003240e6b683123fe89b6 100644
--- a/src/plugins/dive/build.ml
+++ b/src/plugins/dive/build.ml
@@ -32,6 +32,16 @@ end
 
 let dkey = Self.register_category "build"
 
+type locstack = Cil_types.stmt * Callstack.t
+
+(* Generalized statements *)
+
+(* used to *localize* (defines in which functions/file rectangles the node must
+   be placed) nodes *)
+type gstmt =
+  | Local of locstack (* Function statement in a specific callstack *)
+  | Global of Cil_types.varinfo (* Initialization of a global variable *)
+
 
 (* --- Lval enumeration --- *)
 
@@ -89,9 +99,12 @@ struct
 
   let at_start_of = at_start_of
   let after = after
-  let after_kinstr = function
-    | Kglobal -> at_start (* After global initialization *)
-    | Kstmt stmt -> after stmt
+  let before_gstmt = function
+    | Global _ -> at_start
+    | Local (stmt,_) -> before stmt
+  let after_gstmt = function
+    | Global _ -> at_start (* After global initialization *)
+    | Local (stmt,_) -> after stmt
 
   let to_kf_list kinstr callee =
     before_kinstr kinstr |> eval_callee callee |>
@@ -100,11 +113,11 @@ struct
   let to_cvalue request lval =
     eval_lval lval request |> as_cvalue
 
-  let to_location kinstr lval =
-    before_kinstr kinstr |> eval_address lval |> as_location
+  let to_location gstmt lval =
+    before_gstmt gstmt |> eval_address lval |> as_location
 
-  let to_zone kinstr lval =
-    before_kinstr kinstr |> eval_address lval |> as_zone
+  let to_zone gstmt lval =
+    before_gstmt gstmt |> eval_address lval |> as_zone
 
   let to_callstacks stmt =
     before stmt |> callstacks
@@ -113,28 +126,20 @@ struct
     let zone = eval_address lval request |> as_zone in
     is_tainted zone request |> Result.to_option
 
-  let studia_direct_effect = function
-    | e, { Studia.Writes.direct = true } -> Some e
-    | _ -> None
-
-  let writes kinstr lval =
-    let zone = to_zone kinstr lval in
-    Self.debug ~dkey "computing writes for %a" Cil_printer.pp_lval lval;
-    let result = Studia.Writes.compute zone in
-    let writes = List.filter_map studia_direct_effect result in
+  let writes zone =
+    Self.debug ~dkey "computing writes for %a" Locations.Zone.pretty zone;
+    let writes = Studia.Writes.compute zone in
     Self.debug ~dkey "%d found" (List.length writes);
     writes
 
-  let reads kinstr lval =
-    let zone = to_zone kinstr lval in
-    Self.debug ~dkey "computing reads for %a" Cil_printer.pp_lval lval;
-    let result = Studia.Reads.compute zone in
-    let reads = List.filter_map studia_direct_effect result in
+  let reads zone =
+    Self.debug ~dkey "computing reads for %a" Locations.Zone.pretty zone;
+    let reads = Studia.Reads.compute zone in
     Self.debug ~dkey "%d found" (List.length reads);
     reads
 
   let does_lval_read_zone zone stmt lval =
-    let zone' = to_zone (Kstmt stmt) lval in
+    let zone' = to_zone (Local (stmt,[])) lval in
     Locations.Zone.intersects zone' zone
 
   let does_exp_read_zone zone stmt exp =
@@ -148,14 +153,14 @@ end
 (* --- Precision evaluation --- *)
 
 (* For folded bases, lval may be strictly included in the node zone *)
-let update_node_values node ?(lval=Node_kind.to_lval node.node_kind) rq =
+let update_node_values context node ?(lval=Node_kind.to_lval node.node_kind) rq =
   match lval with
   | None -> () (* can't evaluate node *)
   | Some lval ->
     let typ = Cil.typeOfLval lval
     and cvalue = Eval.to_cvalue rq lval
     and taint = Eval.is_tainted rq lval in
-    Graph.update_node_values node ~typ ~cvalue ~taint
+    Context.update_node_values context node ~typ ~cvalue ~taint
 
 
 (* --- Locations handling --- *)
@@ -171,10 +176,10 @@ let is_foldable_type typ =
   | TNamed _ -> assert false (* the type have been unrolled *)
 
 
-let enumerate_cells ~is_folded_base lval kinstr =
+let enumerate_cells ~is_folded_base gstmt lval =
   (* If possible, refine the lval to a non-symbolic one *)
   let typ = Cil.typeOfLval lval in
-  let location = Eval.to_location kinstr lval in
+  let location = Eval.to_location gstmt lval in
   let open Locations in
   let map_base (base,ival) =
     match base with
@@ -201,43 +206,58 @@ let enumerate_cells ~is_folded_base lval kinstr =
   try
     Location_Bits.to_seq_i location.loc |> Seq.flat_map map_base
   with Abstract_interp.Error_Top ->
-    Seq.return (Unknown (lval, kinstr))
+  match gstmt with
+  | Local (stmt,_) -> Seq.return (Unknown (lval, stmt))
+  | Global _vi ->
+    Seq.return (Error "Global initialization address cannot be resolved")
 
-let build_node_kind ~is_folded_base lval kinstr =
+let build_node_kind ~is_folded_base gstmt lval =
   match lval with
   | Var vi, offset ->
     (* Build a scalar node even if kinstr is dead *)
     Scalar (vi, Cil.typeOfLval lval, offset)
   | Mem _, _ ->
-    let cells_seq = enumerate_cells ~is_folded_base lval kinstr in
+    let cells_seq = enumerate_cells ~is_folded_base gstmt lval in
     match cells_seq () with
     | Seq.Cons (node_kind, seq) when Seq.is_empty seq -> node_kind
-    | _ -> Scattered (lval, kinstr)
-
-let default_node_locality callstack =
-  match callstack with
-  | [] ->
-    (* The empty callstack can be used for global lvalues *)
-    { loc_file="" ; loc_callstack=[] }
-  | (kf,_kinstr) :: _ ->
-    let loc_file = get_loc_filename (Kernel_function.get_location kf) in
-    { loc_file ; loc_callstack=callstack }
-
-let build_node_locality callstack node_kind =
-  match Node_kind.get_base node_kind with
-  | None -> default_node_locality callstack
-  | Some vi ->
-    match Kernel_function.find_defining_kf vi with
-    | Some kf ->
-      let callstack =
-        try
-          Callstack.pop_downto kf callstack
-        with Failure _ ->
-          Callstack.init kf (* TODO: complete callstack *)
-      in
-      default_node_locality callstack
-    | None ->
-      { loc_file = get_loc_filename vi.vdecl ; loc_callstack = [] }
+    | _ ->
+      match gstmt with
+      | Local (stmt ,_) -> Scattered (lval, stmt)
+      | Global _vi -> Error "Global initialization address cannot be resolved"
+
+
+let build_node_locality gstmt node_kind =
+  let make_local callstack =
+    match callstack with
+    | [] -> assert false
+    | (kf,_kinstr) :: _ ->
+      let loc_file = get_loc_filename (Kernel_function.get_location kf) in
+      { loc_file ; loc_callstack=callstack }
+  in
+  let make_global vi =
+    { loc_file=get_loc_filename vi.vdecl; loc_callstack=[] }
+  in
+  match gstmt with
+  | Local (_, callstack) ->
+    begin match node_kind with
+      | Scalar (vi,_,_) | Composite (vi) ->
+        begin match Kernel_function.find_defining_kf vi with
+          | Some kf ->
+            let callstack =
+              try
+                Callstack.pop_downto kf callstack
+              with Failure _ ->
+                Callstack.init kf (* TODO: complete callstack *)
+            in
+            make_local callstack
+          | None -> make_global vi
+        end
+      | Scattered _ | Unknown _ | Alarm _ | AbsoluteMemory | String _ | Const _
+      | Error _ ->
+        make_local callstack
+    end
+  | Global vi ->
+    make_global vi
 
 let find_compatible_callstacks stmt callstack =
   let kf = Kernel_function.find_englobing_kf stmt in
@@ -264,196 +284,242 @@ let find_compatible_callstacks stmt callstack =
 
 (* --- Graph building --- *)
 
-let add_or_update_node context callstack node_kind =
-  let node_locality = build_node_locality callstack node_kind in
-  Context.add_node context ~node_kind ~node_locality
+let add_or_update_node ~context gstmt node_kind =
+  let node_locality = build_node_locality gstmt node_kind in
+  let node = Context.add_node context ~node_kind ~node_locality in
+  begin match node_kind with (* Some nodes don't have read or write deps *)
+    | Alarm _ ->
+      node.node_reads_computation <- Done
+    | Unknown _ | Const _ | String _ ->
+      node.node_writes_computation <- Done
+    | Error _ ->
+      node.node_reads_computation <- Done;
+      node.node_writes_computation <- Done
+    | _ -> ()
+  end;
+  node
 
-let build_node context callstack lval kinstr =
+let build_node ~context gstmt lval =
   let is_folded_base = Context.is_folded context in
-  let node_kind = build_node_kind ~is_folded_base lval kinstr in
-  add_or_update_node context callstack node_kind
+  let node_kind = build_node_kind ~is_folded_base gstmt lval in
+  add_or_update_node ~context gstmt node_kind
 
-let build_var context callstack varinfo =
+let build_var ~context gstmt varinfo =
   let lval = Var varinfo, NoOffset in
-  build_node context callstack lval Kglobal
+  build_node ~context gstmt lval
 
-let build_lval context callstack kinstr lval =
-  let node = build_node context callstack lval kinstr in
-  update_node_values ~lval:(Some lval) node (Eval.after_kinstr kinstr);
+let build_lval ~context gstmt lval =
+  let node = build_node ~context gstmt lval in
+  update_node_values context ~lval:(Some lval) node (Eval.after_gstmt gstmt);
   node
 
-let build_const context callstack exp =
-  add_or_update_node context callstack (Const exp)
+let build_const ~context gstmt exp =
+  add_or_update_node ~context gstmt (Const exp)
 
-let build_alarm context callstack stmt alarm =
+let build_alarm ~context (stmt,_ as locstack) alarm =
   let node_kind = Alarm (stmt,alarm) in
-  let node_locality = build_node_locality callstack node_kind in
+  let node_locality = build_node_locality (Local locstack) node_kind in
   Context.add_node context ~node_kind ~node_locality
 
 
 (* --- Writes --- *)
 
+let compatible_writes callstack = function
+  | Studia.Writes.CallIndirect _ -> None (* Ignore indirect writes *)
+  | Assign _ | CallDirect _ | GlobalInit _ as w -> Some w
+  | FormalInit (vi, _callsites) as w ->
+    match Callstack.pop callstack with
+    | Some (kf,stmt,_callstack) ->
+      (* keep the only callsite compatible with the current callstack *)
+      Some (Studia.Writes.FormalInit (vi, [(kf,[stmt])]))
+    | None -> Some w
+
+(* returns true if the callsite (kf,stmt) *)
+
 type deps_builder = unit Seq.t
 
 let build_node_writes context node =
-  let graph = Context.get_graph context
-  and is_folded_base = Context.is_folded context in
+  let is_folded_base = Context.is_folded context in
 
-  let rec build_write_deps callstack kinstr lval : deps_builder =
-    let add_deps = function
-      | { skind=Instr instr } as stmt ->
+  let rec build_write_deps ~callstack zone : deps_builder =
+    let add_deps origin =
+      match origin with
+      | Studia.Writes.CallIndirect _ ->
+        Seq.empty (* Ignore indirect writes *)
+
+      | Assign stmt | CallDirect stmt ->
+        let instr = match stmt.skind with
+          | Instr instr -> instr
+          | _ -> assert false (* Studia invariant *)
+        in
         (* Update the values at the light of new discovered write *)
-        update_node_values node (Eval.after stmt);
+        update_node_values context node (Eval.after stmt);
         (* Add dependencies for each callstack *)
         List.to_seq (find_compatible_callstacks stmt callstack) |>
-        Seq.flat_map (fun cs -> build_instr_deps cs stmt instr)
-      | _ -> assert false (* Studia invariant *)
+        Seq.flat_map
+          (fun cs -> build_instr_deps ~callstack:cs ~origin stmt instr)
+
+      | GlobalInit (vi, initinfo) as origin ->
+        let init = match initinfo.init with
+          | None -> SingleInit (Cil.zero ~loc:vi.vdecl)
+          | Some init -> init
+        in
+        build_init_deps ~origin (Global vi) vi init
+
+      | FormalInit (vi, callsites) as origin ->
+        let kf = Option.get (Kernel_function.find_defining_kf vi) in
+        let pos = Kernel_function.get_formal_position vi kf in
+        let add_deps stmt =
+          match stmt.skind with
+          | Instr
+              (Call (_,_,args,_) |
+               (Local_init (_, ConsInit (_, args, _), _))) ->
+            let exp = List.nth args pos in
+            let callstack =
+              match Callstack.pop callstack with
+              | Some (_kf,_stmt,callstack') -> callstack'
+              | None -> Callstack.init kf
+            in
+            build_exp_deps ~origin (Local (stmt, callstack)) Data exp
+          | _ ->
+            assert false (* Callsites can only be Call or ConsInit *)
+        in
+        (* Evaluate the parameter values at the start of its defining function *)
+        update_node_values context node (Eval.at_start_of kf);
+        let callsites = List.concat_map snd callsites in
+        Seq.flat_map add_deps (List.to_seq callsites)
     in
-    let writes = Eval.writes kinstr lval in
-    let args_seq, call_stmts = build_arg_deps callstack in
-    let compare = Cil_datatype.Stmt_Id.compare in
-    node.node_writes_stmts <- List.sort_uniq compare (writes @ call_stmts);
-    Seq.append args_seq (Seq.flat_map add_deps (List.to_seq writes))
-
-  and build_alarm_deps callstack stmt alarm : deps_builder =
-    build_lvals_deps callstack stmt Data (EnumLvals.in_alarm alarm)
-
-  and build_instr_deps callstack stmt instr : deps_builder =
+    let writes = Eval.writes zone in
+    let writes = List.filter_map (compatible_writes callstack) writes in
+    Context.set_node_writes context node writes;
+    Seq.flat_map add_deps (List.to_seq writes)
+
+  and build_alarm_deps ~callstack stmt alarm : deps_builder =
+    let lvals = EnumLvals.in_alarm alarm in
+    let origin = Studia.Writes.Assign stmt in
+    let gstmt = Local (stmt, callstack) in
+    build_lvals_deps ~origin gstmt Data lvals
+
+  and build_instr_deps ~origin ~callstack stmt instr : deps_builder =
+    let gstmt = Local (stmt, callstack) in
     (* Add dependencies found in the instruction *)
     match instr with
     | Set (_, exp, _) ->
-      build_exp_deps callstack stmt Data exp
+      build_exp_deps ~origin gstmt Data exp
     | Call (_, callee, args, _) ->
-      build_call_deps callstack stmt callee args
+      build_call_deps ~callstack ~origin stmt callee args
     | Local_init (dest, ConsInit (f, args, k), loc) ->
       let as_func _dest callee args _loc =
-        build_call_deps callstack stmt callee args
+        build_call_deps ~callstack ~origin stmt callee args
       in
       Cil.treat_constructor_as_func as_func dest f args k loc
     | Local_init (vi, AssignInit init, _)  ->
-      let lvals = EnumLvals.in_init vi init in
-      let exp =
-        match init with
-        | CompoundInit _ -> None (* Do not generate nodes for Compounds for now *)
-        | SingleInit exp -> Some exp
-      in
-      build_lvals_deps callstack stmt Data ?exp lvals
+      build_init_deps ~origin gstmt vi init
     | Asm _ | Skip _ | Code_annot _ -> Seq.empty (* Cases not returned by Studia *)
 
-  and build_arg_deps callstack : deps_builder * stmt list =
-    match Node_kind.get_base node.node_kind with
-    (* TODO refine formal dependency computation for non-scalar formals *)
-    | Some vi when vi.vformal ->
-      let kf = Option.get (Kernel_function.find_defining_kf vi) in
-      let pos = Kernel_function.get_formal_position vi kf in
-      let callsites =
-        match Callstack.pop callstack with
-        | Some (kf',stmt,callstack) ->
-          assert (Kernel_function.equal kf' kf);
-          [(stmt,callstack)]
-        | None ->
-          let callsites = Kernel_function.find_syntactic_callsites kf in
-          List.map (fun (kf,stmt) -> (stmt,Callstack.init kf)) callsites
-      and add_deps (stmt,callstack) : unit Seq.t =
-        match stmt.skind with
-        | Instr
-            (Call (_,_,args,_) |
-             (Local_init (_, ConsInit (_, args, _), _))) ->
-          let exp = List.nth args pos in
-          build_exp_deps callstack stmt Data exp
-        | _ ->
-          assert false (* Callsites can only be Call or ConsInit *)
-      in
-      (* Evaluate the parameter values at the start of its defining function *)
-      update_node_values node (Eval.at_start_of kf);
-      Seq.flat_map add_deps (List.to_seq callsites), List.map fst callsites
-    | _ -> Seq.empty, []
-
-  and build_return_deps callstack stmt args kf : deps_builder =
+  and build_return_deps ~callstack call_stmt args kf : deps_builder =
     match Kernel_function.find_return kf with
     | {skind = Return (Some {enode = Lval lval_res},_)} as return_stmt ->
-      let callstack = Callstack.push (kf,stmt) callstack in
-      build_lval_deps callstack return_stmt Data lval_res
+      let callstack = Callstack.push (kf,call_stmt) callstack in
+      let origin = Studia.Writes.Assign return_stmt in
+      let gstmt = Local (return_stmt, callstack) in
+      build_lval_deps ~origin gstmt Data lval_res
     | {skind = Return (None, _)} -> Seq.empty (* return void *)
     | _ -> assert false (* Cil invariant *)
     | exception Kernel_function.No_Statement ->
       (* the function is only a prototype *)
       (* TODO: read assigns instead *)
+      let origin = Studia.Writes.Assign call_stmt in
+      let gstmt = Local (call_stmt, callstack) in
       List.to_seq args |>
-      Seq.flat_map (build_exp_deps callstack stmt Data)
+      Seq.flat_map (build_exp_deps ~origin gstmt Data)
 
-  and build_call_deps callstack stmt callee args : deps_builder =
+  and build_call_deps ~origin ~callstack stmt callee args : deps_builder =
+    let gstmt = Local (stmt, callstack) in
     let callee_deps = match callee.enode with
       | Lval (Var _vi, _offset) -> Seq.empty
       | Lval (Mem exp, _offset) ->
-        build_exp_deps callstack stmt Callee exp
+        build_exp_deps ~origin gstmt Callee exp
       | _ ->
         Self.warning "Cannot compute all callee dependencies for %a"
           Cil_printer.pp_stmt stmt;
         Seq.empty
     and return_deps =
       List.to_seq (Eval.to_kf_list (Kstmt stmt) callee) |>
-      Seq.flat_map (build_return_deps callstack stmt args)
+      Seq.flat_map (build_return_deps ~callstack stmt args)
     in
     Seq.append callee_deps return_deps
 
-  and build_exp_deps callstack stmt kind exp : deps_builder =
+  and build_init_deps ~origin gstmt vi init : deps_builder =
+    let lvals = EnumLvals.in_init vi init in
+    let exp =
+      match init with
+      | CompoundInit _ -> None (* Do not generate nodes for Compounds for now *)
+      | SingleInit exp -> Some exp
+    in
+    build_lvals_deps ~origin gstmt Data ?exp lvals
+
+  and build_exp_deps ~origin gstmt kind exp : deps_builder =
     let lvals = EnumLvals.in_exp exp in
-    build_lvals_deps callstack stmt kind ~exp lvals
+    build_lvals_deps ~origin gstmt kind ~exp lvals
 
-  and build_lvals_deps callstack stmt kind ?exp lvals : deps_builder =
+  and build_lvals_deps ~origin gstmt kind ?exp lvals : deps_builder =
     if lvals <> [] then
       List.to_seq lvals |>
-      Seq.flat_map (build_lval_deps callstack stmt kind)
+      Seq.flat_map (build_lval_deps ~origin gstmt kind)
     else
-      Option.fold exp ~none:Seq.empty
-        ~some:(build_const_deps callstack stmt kind)
+      Option.to_seq exp |>
+      Seq.flat_map (build_const_deps ~origin gstmt kind)
 
-  and build_lval_deps callstack stmt kind lval : deps_builder =
-    let kinstr = Kstmt stmt in
-    let dst = build_lval context callstack kinstr lval in
-    Seq.return (Graph.create_dependency graph kinstr dst kind node)
+  and build_lval_deps ~origin gstmt kind lval : deps_builder =
+    let dst = build_lval ~context gstmt lval in
+    Seq.return (Context.add_dep context ~origin ~kind dst node)
 
-  and build_const_deps callstack stmt kind exp : deps_builder =
-    let kinstr = Kstmt stmt in
-    let dst = build_const context callstack exp in
-    Seq.return (Graph.create_dependency graph kinstr dst kind node)
+  and build_const_deps ~origin gstmt kind exp : deps_builder =
+    let dst = build_const ~context gstmt exp in
+    Seq.return (Context.add_dep context ~origin ~kind dst node)
 
-  and build_scattered_deps callstack kinstr lval : deps_builder =
+  and build_scattered_deps ~callstack stmt lval : deps_builder =
+    let gstmt = Local (stmt,callstack) in
     let add_cell node_kind =
-      let node' = add_or_update_node context callstack node_kind in
-      update_node_values node (Eval.after_kinstr kinstr);
-      Graph.create_dependency graph kinstr node' Composition node
+      let dst = add_or_update_node ~context gstmt node_kind in
+      update_node_values context node (Eval.after stmt);
+      let origin = Studia.Writes.Assign stmt in
+      Context.add_dep context ~origin ~kind:Composition dst node
     in
-    enumerate_cells ~is_folded_base lval kinstr |> Seq.map add_cell
+    enumerate_cells ~is_folded_base gstmt lval |> Seq.map add_cell
   in
 
   let callstack = node.node_locality.loc_callstack in
   match node.node_kind with
-  | Scalar (vi,_typ,offset) ->
-    build_write_deps callstack Kglobal (Cil_types.Var vi, offset)
+  | Scalar (vi, _typ, offset) ->
+    let zone = Eval.to_zone (Global vi) (Cil_types.Var vi, offset) in
+    build_write_deps ~callstack zone
   | Composite (vi) ->
-    build_write_deps callstack Kglobal (Cil_types.Var vi, Cil_types.NoOffset)
-  | Scattered (lval,kinstr) ->
-    build_scattered_deps callstack kinstr lval
-  | Alarm (stmt,alarm) ->
-    build_alarm_deps callstack stmt alarm
+    let zone = Locations. zone_of_varinfo vi in
+    build_write_deps ~callstack zone
+  | Scattered (lval, stmt) ->
+    build_scattered_deps ~callstack stmt lval
+  | Alarm (stmt, alarm) ->
+    build_alarm_deps ~callstack stmt alarm
   | Unknown _ | AbsoluteMemory | String _ | Const _ | Error _ ->
     Seq.empty
 
 
 (* --- Reads --- *)
 
-let build_node_reads context node =
-  let graph = Context.get_graph context in
+let compatible_reads = function
+  | Studia.Reads.Indirect _ -> None
+  | Direct stmt -> Some stmt
 
-  let rec build_reads_deps callstack kinstr lval : deps_builder =
+let build_node_reads context node =
+  let rec build_reads_deps callstack zone : deps_builder =
     let add_deps stmt =
-      let zone = Some (Eval.to_zone kinstr lval) in
       List.to_seq (find_compatible_callstacks stmt callstack) |>
-      Seq.flat_map (fun cs -> build_stmt_deps cs zone stmt)
+      Seq.flat_map (fun cs -> build_stmt_deps ~callstack:cs (Some zone) stmt)
     in
-    List.to_seq (Eval.reads kinstr lval) |>
+    Eval.reads zone |> List.to_seq |>
+    Seq.filter_map compatible_reads |>
     Seq.flat_map add_deps
 
   and exp_contains_read zone stmt exp =
@@ -468,11 +534,7 @@ let build_node_reads context node =
     | Some zone' ->
       Eval.does_init_read_zone zone' stmt vi init
 
-  and build_kinstr_deps callstack zone = function
-    | Kglobal -> Seq.empty (* Do nothing *)
-    | Kstmt stmt -> build_stmt_deps callstack zone stmt
-
-  and build_stmt_deps callstack zone stmt =
+  and build_stmt_deps ~callstack zone stmt =
     match stmt.skind with
     | Instr instr -> build_instr_deps callstack zone stmt instr
     | Return (Some exp,_)
@@ -483,7 +545,7 @@ let build_node_reads context node =
   and build_instr_deps callstack zone stmt = function
     | Set (lval, exp, _)
       when exp_contains_read zone stmt exp ->
-      build_lval_deps callstack stmt lval
+      build_lval_deps ~callstack stmt lval
     | Local_init (dest, ConsInit (f, args, k), loc) ->
       let as_func _dest callee args _loc =
         build_call_deps callstack zone stmt callee args
@@ -491,7 +553,7 @@ let build_node_reads context node =
       Cil.treat_constructor_as_func as_func dest f args k loc
     | Local_init (vi, AssignInit init, _)
       when init_contains_read zone stmt vi init ->
-      build_var_deps callstack stmt vi
+      build_var_deps ~callstack stmt vi
     | Call (_, callee, args, _) ->
       build_call_deps callstack zone stmt callee args
     | _ -> Seq.empty
@@ -510,9 +572,9 @@ let build_node_reads context node =
       match stmt.skind with
       | Instr (Call (None,_,_,_)) -> Seq.empty
       | Instr (Call (Some lval,_,_,_)) ->
-        build_lval_deps callstack stmt lval
+        build_lval_deps ~callstack stmt lval
       | Instr (Local_init (vi,_,_)) ->
-        build_var_deps callstack stmt vi
+        build_var_deps ~callstack stmt vi
       | _ ->
         assert false (* Callsites can only be Call or ConsInit *)
     in
@@ -533,26 +595,30 @@ let build_node_reads context node =
 
   and build_arg_dep callstack stmt zone (arg,formal) =
     if exp_contains_read zone stmt arg
-    then build_var_deps callstack stmt formal
+    then build_var_deps ~callstack stmt formal
     else Seq.empty
 
-  and build_lval_deps callstack stmt lval =
-    let kinstr = Kstmt stmt in
-    let src = build_lval context callstack kinstr lval in
-    Seq.return (Graph.create_dependency graph kinstr node Data src)
+  and build_lval_deps ~callstack stmt lval =
+    let gstmt = Local (stmt, callstack) in
+    let src = build_lval ~context gstmt lval in
+    let origin = Studia.Writes.Assign stmt in
+    Seq.return (Context.add_dep context ~origin ~kind:Data node src)
 
-  and build_var_deps callstack stmt vi =
-    build_lval_deps callstack stmt (Cil.var vi)
+  and build_var_deps ~callstack stmt vi =
+    build_lval_deps ~callstack stmt (Cil.var vi)
 
   in
   let callstack = node.node_locality.loc_callstack in
   match node.node_kind with
   | Scalar (vi,_typ,offset) ->
-    build_reads_deps callstack Kglobal (Cil_types.Var vi, offset)
+    (* Offset should be constant and no evaluation should be required *)
+    let zone = Eval.to_zone (Global vi) (Cil_types.Var vi, offset) in
+    build_reads_deps callstack zone
   | Composite (vi) ->
-    build_reads_deps callstack Kglobal (Cil_types.Var vi, Cil_types.NoOffset)
-  | Scattered (_lval,kinstr) ->
-    build_kinstr_deps callstack None kinstr
+    let zone = Locations. zone_of_varinfo vi in
+    build_reads_deps callstack zone
+  | Scattered (_lval,stmt) ->
+    build_stmt_deps ~callstack None stmt
   | Alarm _ | Unknown _ | AbsoluteMemory | Const _ | String _ | Error _ ->
     Seq.empty
 
@@ -594,8 +660,7 @@ let explore_backward ~depth context root =
         | Partial builder -> builder
         | NotDone -> build_node_writes context n
       in
-      n.node_writes_computation <- advance_computation context deps_builder;
-      Context.update_diff context n
+      n.node_writes_computation <- advance_computation context deps_builder
     end
   in
   bfs ~depth ~iter_succ explore_node root
@@ -610,8 +675,7 @@ let explore_forward ~depth context root =
         | Partial builder -> builder
         | NotDone -> build_node_reads context n
       in
-      n.node_reads_computation <- advance_computation context deps_builder;
-      Context.update_diff context n
+      n.node_reads_computation <- advance_computation context deps_builder
     end
   in
   bfs ~depth ~iter_succ explore_node root
@@ -623,22 +687,23 @@ let complete context root =
   Context.add_root context root;
   root
 
-let add_var context varinfo =
-  let callstack = [] in
-  let node = build_var context callstack varinfo in
+let add_var context vi =
+  let gstmt = match Kernel_function.find_defining_kf vi with
+    | Some kf -> Local (Kernel_function.find_first_stmt kf , Callstack.init kf)
+    | None -> Global vi
+  in
+  let node = build_var ~context gstmt vi in
   complete context node
 
-let add_lval context kinstr lval =
-  let callstack = match kinstr with
-    | Kglobal -> []
-    | Kstmt stmt -> Callstack.init (Kernel_function.find_englobing_kf stmt)
-  in
-  let node = build_lval context callstack kinstr lval in
+let add_lval context stmt lval =
+  let callstack = Callstack.init (Kernel_function.find_englobing_kf stmt) in
+  let gstmt = Local (stmt, callstack) in
+  let node = build_lval ~context gstmt lval in
   complete context node
 
 let add_alarm context stmt alarm =
   let callstack = Callstack.init (Kernel_function.find_englobing_kf stmt) in
-  let node = build_alarm context callstack stmt alarm in
+  let node = build_alarm ~context (stmt, callstack) alarm in
   complete context node
 
 let add_annotation context stmt annot =
@@ -647,7 +712,7 @@ let add_annotation context stmt annot =
 
 let add_instr context stmt = function
   | Set (lval, _, _)
-  | Call (Some lval, _, _, _) -> Some (add_lval context (Kstmt stmt) lval)
+  | Call (Some lval, _, _, _) -> Some (add_lval context stmt lval)
   | Local_init (vi, _, _) -> Some (add_var context vi)
   | Code_annot (annot, _) -> add_annotation context stmt annot
   | _ -> None (* Do nothing for any other instruction *)
@@ -663,9 +728,9 @@ let add_property context = function
   | _ -> None (* Do nothing fo any other property *)
 
 let add_localizable context = function
-  | Printer_tag.PLval (_kf, kinstr, lval) -> Some (add_lval context kinstr lval)
+  | Printer_tag.PIP prop -> add_property context prop
+  | PLval (_kf, Kstmt stmt, lval) -> Some (add_lval context stmt lval)
   | PVDecl (_kf, _kinstr, varinfo) -> Some (add_var context varinfo)
-  | PIP (prop) -> add_property context prop
   | PStmt (_kf, stmt) | PStmtStart (_kf, stmt) -> add_stmt context stmt
   | _ -> None (* Do nothing for any other localizable *)
 
@@ -674,12 +739,10 @@ let add_localizable context = function
 
 let remove_dependencies context node =
   (* Remove incomming edges *)
-  Graph.remove_dependencies (Context.get_graph context) node;
-  (* Dependencies are not there anymore *)
+  Context.remove_node_deps context node;
+  (* Reset the writes computation status *)
   node.node_writes_computation <- NotDone;
-  node.node_writes_stmts <- [];
-  (* Notify node update *)
-  Context.update_diff context node
+  Context.set_node_writes context node []
 
 let remove_disconnected context =
   let roots = Context.get_roots context in
diff --git a/src/plugins/dive/build.mli b/src/plugins/dive/build.mli
index 22893c9a394472dfdda40cef86572a230169ed6f..f73a88ab2a29cede25733371e5cee8377a6f0ec7 100644
--- a/src/plugins/dive/build.mli
+++ b/src/plugins/dive/build.mli
@@ -24,7 +24,7 @@ open Cil_types
 open Dive_types
 open Context
 
-val add_lval : t -> kinstr -> lval -> node
+val add_lval : t -> stmt -> lval -> node
 val add_var : t -> varinfo -> node
 val add_alarm : t -> stmt -> Alarms.alarm -> node
 val add_annotation : t -> stmt -> code_annotation -> node option
diff --git a/src/plugins/dive/context.ml b/src/plugins/dive/context.ml
index b0a3dd3e4a74954a32c9a76e997e0cb1cefa7091..c3482a199e7dbfc7ba101f2fd1d346ec6389dfae 100644
--- a/src/plugins/dive/context.ml
+++ b/src/plugins/dive/context.ml
@@ -24,8 +24,6 @@ open Dive_types
 
 module Graph = Dive_graph
 
-let dkey = Self.register_category "context"
-
 
 module NodeRef = Datatype.Pair_with_collections
     (Node_kind) (Callstack)
@@ -36,6 +34,8 @@ module NodeTable = FCHashtbl.Make (NodeRef)
 module NodeSet = Graph.Node.Set
 module BaseSet = Cil_datatype.Varinfo.Set
 
+type element = Node of node | Edge of (node * dependency * node)
+
 type t = {
   mutable graph: Graph.t;
   mutable vertex_table: node Index.t; (* node_key -> node *)
@@ -44,14 +44,17 @@ type t = {
   mutable hidden_bases: BaseSet.t;
   mutable max_dep_fetch_count: int;
   mutable roots: NodeSet.t;
-  mutable graph_diff: graph_diff;
+  mutable update_hook : element -> unit;
+  mutable remove_hook : element -> unit;
+  mutable clear_hook : unit -> unit;
 }
 
 
 (* --- initialization --- *)
 
+let no_hook = fun _ -> ()
+
 let create () =
-  Eva.Analysis.compute ();
   {
     graph = Graph.create ();
     vertex_table = Index.create 13;
@@ -60,7 +63,9 @@ let create () =
     hidden_bases = BaseSet.empty;
     max_dep_fetch_count = 10;
     roots = NodeSet.empty;
-    graph_diff = { last_root = None ; added_nodes=[] ; removed_nodes=[] };
+    update_hook = no_hook;
+    remove_hook = no_hook;
+    clear_hook = no_hook;
   }
 
 let clear context =
@@ -69,7 +74,22 @@ let clear context =
   context.node_table <- NodeTable.create 13;
   context.max_dep_fetch_count <- 10;
   context.roots <- NodeSet.empty;
-  context.graph_diff <- { last_root = None ; added_nodes=[] ; removed_nodes=[] }
+  context.clear_hook ()
+
+
+(* Hooks *)
+
+let set_update_hook context f =
+  context.update_hook <- f
+
+let set_remove_hook context f =
+  context.remove_hook <- f
+
+let set_clear_hook context f =
+  context.clear_hook <- f
+
+let notify_node_update context node =
+  context.update_hook (Node node)
 
 
 (* --- Accessors --- *)
@@ -84,36 +104,6 @@ let get_max_dep_fetch_count context =
   context.max_dep_fetch_count
 
 
-(* --- State --- *)
-
-let is_node_updated context node =
-  let is_node n = Graph.Node.equal node n in
-  List.exists is_node context.graph_diff.removed_nodes ||
-  List.exists is_node context.graph_diff.added_nodes
-
-let update_diff context node =
-  if not (is_node_updated context node) then
-    context.graph_diff <- {
-      context.graph_diff with
-      added_nodes = node :: context.graph_diff.added_nodes;
-    }
-
-let take_last_diff context =
-  let pp_node fmt n = Format.pp_print_int fmt n.node_key in
-  let pp_node_list = Pretty_utils.pp_list ~sep:",@, " pp_node in
-  let diff = context.graph_diff in
-  Self.debug ~dkey "root: %a,@, added: %a,@, subbed: %a"
-    (Pretty_utils.pp_opt pp_node) diff.last_root
-    pp_node_list diff.added_nodes
-    pp_node_list diff.removed_nodes;
-  context.graph_diff <- {
-    last_root = None ;
-    added_nodes=[] ;
-    removed_nodes=[]
-  };
-  diff
-
-
 (* --- Roots --- *)
 
 let get_roots context =
@@ -123,15 +113,11 @@ let update_roots context new_roots =
   let old_roots = context.roots in
   context.roots <- new_roots;
   let unset n =
-    if not (NodeSet.mem n new_roots) then begin
-      n.node_is_root <- false;
-      update_diff context n
-    end
+    n.node_is_root <- false;
+    context.update_hook (Node n);
   and set n =
-    if not (NodeSet.mem n old_roots) then begin
-      n.node_is_root <- true;
-      update_diff context n
-    end
+    n.node_is_root <- true;
+    context.update_hook (Node n);
   in
   NodeSet.iter unset old_roots;
   NodeSet.iter set new_roots
@@ -180,7 +166,7 @@ let add_node context ~node_kind ~node_locality =
     let node = Graph.create_node context.graph ~node_kind ~node_locality in
     node.node_hidden <- is_hidden context node.node_kind;
     Index.add context.vertex_table node.node_key node;
-    update_diff context node;
+    context.update_hook (Node node);
     node
   in
   NodeTable.memo context.node_table node_ref add_new
@@ -190,12 +176,28 @@ let remove_node context node =
   let graph = context.graph in
   Graph.iter_succ (fun n -> n.node_writes_computation <- NotDone) graph node;
   Graph.iter_pred (fun n -> n.node_reads_computation <- NotDone) graph node;
+  Graph.iter_succ_e (fun e -> context.remove_hook (Edge e)) graph node;
+  Graph.iter_pred_e (fun e -> context.remove_hook (Edge e)) graph node;
   Graph.remove_node context.graph node;
   Index.remove context.vertex_table node.node_key;
   NodeTable.remove context.node_table node_ref;
-  let is_not_node n = not (Graph.Node.equal node n) in
-  context.graph_diff <- {
-    context.graph_diff with
-    added_nodes = List.filter is_not_node context.graph_diff.added_nodes;
-    removed_nodes = node :: context.graph_diff.removed_nodes;
-  }
+  context.remove_hook (Node node)
+
+let add_dep context ~origin ~kind src dest =
+  let edge = Graph.create_dependency context.graph ~origin ~kind src dest in
+  context.update_hook (Edge edge)
+
+let remove_dep context edge =
+  Graph.remove_dependency context.graph edge;
+  context.remove_hook (Edge edge)
+
+let remove_node_deps context node =
+  Graph.iter_pred_e (remove_dep context) context.graph node
+
+let update_node_values context node ~typ ~cvalue ~taint =
+  Graph.update_node_values node ~typ ~cvalue ~taint;
+  notify_node_update context node
+
+let set_node_writes context node writes =
+  node.node_writes <- List.sort_uniq Studia.Writes.compare writes;
+  notify_node_update context node
diff --git a/src/plugins/dive/context.mli b/src/plugins/dive/context.mli
index ecc6139bf78ce55e79db800c9313d3131af99c2c..d440e8b54a6c6c545b6fed757482a25d4043a727 100644
--- a/src/plugins/dive/context.mli
+++ b/src/plugins/dive/context.mli
@@ -22,20 +22,13 @@
 
 open Dive_types
 
-(*
-module NodeRef : Datatype.S with type t = node_kind * callstack
-module Index : Datatype.Hashtbl with type key = int
-module NodeTable : Datatype.Hashtbl with type key = NodeRef.t
-module NodeSet : Datatype.Set with type elt = node
-module BaseSet : Datatype.Set with type elt = Cil_types.varinfo
-module FunctionMap : Datatype.Map with type key = Cil_types.kernel_function
-*)
-
 type t
 
+type element = Node of node | Edge of (node * dependency * node)
+
 val create : unit -> t
 val clear : t -> unit (* reset to almost an empty context,
-                         but keeps folded and hidden bases *)
+                         but keeps folded and hidden bases, and hooks *)
 
 val get_graph : t -> Dive_graph.t
 val find_node : t -> int -> node
@@ -56,6 +49,16 @@ val show : t -> Cil_types.varinfo -> unit
 
 val add_node : t -> node_kind:node_kind -> node_locality:node_locality -> node
 val remove_node : t -> node -> unit
+val add_dep : t -> origin:origin -> kind:dependency_kind ->
+  node -> node -> unit
+val remove_node_deps : t -> node -> unit
+
+val update_node_values : t -> node ->
+  typ:Cil_types.typ ->
+  cvalue:Locations.Location_Bytes.t -> taint:Eva.Results.taint option -> unit
+val set_node_writes : t -> node -> origin list -> unit
+
+val set_update_hook : t -> (element -> unit) -> unit
+val set_remove_hook : t -> (element -> unit) -> unit
+val set_clear_hook : t -> (unit -> unit) -> unit
 
-val update_diff : t -> node -> unit
-val take_last_diff : t -> graph_diff
diff --git a/src/plugins/dive/dive_graph.ml b/src/plugins/dive/dive_graph.ml
index d950484cb2fe818cec169dac5b5cdfcef9563fe8..ef3c84076d6d3a39afe77c1c39c0786fc8602102 100644
--- a/src/plugins/dive/dive_graph.ml
+++ b/src/plugins/dive/dive_graph.ml
@@ -40,7 +40,7 @@ let new_node
   node_taint = None;
   node_writes_computation = NotDone;
   node_reads_computation = NotDone;
-  node_writes_stmts = [];
+  node_writes = [];
 }
 
 module Node = Datatype.Make_with_collections
@@ -80,9 +80,9 @@ let create_node ~node_kind ~node_locality g =
 
 let remove_node = remove_vertex
 
-let create_dependency g kinstr v1 dependency_kind v2 =
+let create_dependency g ~origin ~kind v1  v2 =
   let same_kind (_,e,_) =
-    e.dependency_kind = dependency_kind
+    e.dependency_kind = kind
   in
   let matching_edge =
     try
@@ -94,21 +94,19 @@ let create_dependency g kinstr v1 dependency_kind v2 =
     | None ->
       let e = {
         dependency_key = fresh_key ();
-        dependency_kind;
+        dependency_kind = kind;
         dependency_origins = []
       }
       in
       add_edge_e g (v1,e,v2);
       e
   in
-  (* Add origins *)
-  match kinstr with
-  | Cil_types.Kglobal -> ()
-  | Kstmt stmt ->
-    let add_uniq l x =
-      List.sort_uniq Cil_datatype.Stmt.compare (x :: l)
-    in
-    e.dependency_origins <- add_uniq e.dependency_origins stmt
+  (* Add origin *)
+  let add_uniq l x =
+    List.sort_uniq Studia.Writes.compare (x :: l)
+  in
+  e.dependency_origins <- add_uniq e.dependency_origins origin;
+  (v1,e,v2)
 
 
 let remove_dependency g edge =
@@ -117,12 +115,6 @@ let remove_dependency g edge =
 let remove_dependencies g node =
   iter_pred_e (remove_dependency g) g node
 
-let vertices g =
-  fold_vertex (fun n acc -> n ::acc) g []
-
-let edges g =
-  fold_edges_e (fun d acc -> d ::acc) g []
-
 
 let update_node_values node ~typ ~cvalue ~taint =
   let join_taint t1 t2 =
@@ -178,7 +170,7 @@ let bfs ?(iter_succ=iter_succ) ?(limit=max_int) g roots =
   Table.fold (fun n _ l -> n :: l) explored []
 
 
-let ouptput_to_dot out_channel g =
+let output_to_dot out_channel g =
   let open Graph.Graphviz.DotAttributes in
   (* let g = add_dummy_nodes g in *)
 
@@ -267,158 +259,3 @@ let ouptput_to_dot out_channel g =
     end)
   in
   Dot.output_graph out_channel g
-
-module JsonPrinter =
-struct
-  let output_stmt stmt =
-    let kf = Kernel_function.find_englobing_kf stmt in
-    Server.Kernel_ast.Location.to_json (kf, PStmtStart (kf, stmt))
-
-  let output_kinstr = function
-    | Cil_types.Kglobal -> `String "global"
-    | Cil_types.Kstmt stmt -> `Int stmt.Cil_types.sid
-
-  let output_callsite (kf,kinstr) =
-    `Assoc [
-      ("fun", `String (Kernel_function.get_name kf)) ;
-      ("instr", output_kinstr kinstr) ;
-    ]
-
-  let output_callstack cs =
-    `List (List.map output_callsite cs)
-
-  let output_node_kind kind =
-    let s = match kind with
-      | Scalar _ -> "scalar"
-      | Composite _ -> "composite"
-      | Scattered _ -> "scattered"
-      | Unknown _ -> "unknown"
-      | Alarm _ -> "alarm"
-      | AbsoluteMemory -> "absolute"
-      | String _ -> "string"
-      | Const _ -> "const"
-      | Error _ -> "error"
-    in
-    `String s
-
-  let output_node_locality { loc_file ; loc_callstack } =
-    let f1 = ("file", `String loc_file) in
-    let fields = match loc_callstack with
-      | [] -> [f1]
-      | cs -> [f1 ; ("callstack", output_callstack cs)]
-    in
-    `Assoc fields
-
-  let output_range range =
-    match range with
-    | Empty -> `String "empty"
-    | Singleton -> `String "singleton"
-    | Normal range_grade -> `Int range_grade
-    | Wide -> `String "wide"
-
-  let output_dep_kind kind =
-    let s = match kind with
-      | Callee -> "callee"
-      | Data -> "data"
-      | Address -> "addr"
-      | Control -> "ctrl"
-      | Composition -> "comp"
-    in
-    `String s
-
-  let output_node_values values =
-    match values with
-    | None -> `Null
-    | Some cvalue when Cvalue.V.is_bottom cvalue -> `Null
-    | Some cvalue -> `String (Pretty_utils.to_string Cvalue.V.pretty cvalue)
-
-  let output_computation = function
-    | Done -> `String "yes"
-    | Partial _ -> `String "partial"
-    | NotDone -> `String "no"
-
-  let output_taint = function
-    | Eva.Results.Direct -> `String "direct"
-    | Indirect ->  `String "indirect"
-    | Untainted ->  `String "untainted"
-
-  let output_node node =
-    let label = Pretty_utils.to_string Node_kind.pretty node.node_kind in
-    `Assoc ([
-        ("id", `Int node.node_key) ;
-        ("label", `String label) ;
-        ("kind", output_node_kind node.node_kind) ;
-        ("locality", output_node_locality node.node_locality) ;
-        ("is_root", `Bool node.node_is_root) ;
-        ("backward_explored", output_computation node.node_writes_computation) ;
-        ("forward_explored", output_computation node.node_reads_computation) ;
-        ("writes", `List (List.map output_stmt node.node_writes_stmts)) ;
-        ("values",  output_node_values node.node_values) ;
-        ("range",  output_range node.node_range) ;
-      ] @
-        begin match Node_kind.to_lval node.node_kind with
-          | None -> []
-          | Some lval ->
-            let typ = Cil.typeOfLval lval in
-            let str = Pretty_utils.to_string Cil_printer.pp_typ typ in
-            [("type", `String str)]
-        end @
-        begin match node.node_taint with
-          | None -> []
-          | Some t -> [("taint", output_taint t)]
-        end)
-
-  let output_dep (n1,dep,n2) =
-    `Assoc [
-      ("id", `Int dep.dependency_key) ;
-      ("src", `Int n1.node_key) ;
-      ("dst", `Int n2.node_key) ;
-      ("kind", output_dep_kind dep.dependency_kind) ;
-      ("origins", `List (List.map output_stmt dep.dependency_origins)) ;
-    ]
-
-  let output_graph g =
-    `Assoc [
-      ("nodes", `List (List.map output_node (vertices g))) ;
-      ("deps", `List (List.map output_dep (edges g)))
-    ]
-
-  let output_diff g diff =
-    let root = match diff.last_root with
-      | None -> `Null
-      | Some root -> `Int root.node_key
-    and added_nodes = List.map output_node diff.added_nodes
-    and added_deps =
-      let module Set = Set.Make (struct
-          type t = edge
-          let compare (_,d1,_) (_,d2,_) = d1.dependency_key - d2.dependency_key
-        end)
-      in
-      let collect_deps set node =
-        let set = fold_pred_e Set.add g node set in
-        let set = fold_succ_e Set.add g node set in
-        set
-      in
-      let set = List.fold_left collect_deps Set.empty diff.added_nodes in
-      List.map output_dep (Set.elements set)
-    and removed_nodes =
-      List.map (fun node -> `Int node.node_key) diff.removed_nodes
-    in
-    `Assoc [
-      ("root", root) ;
-      ("add", `Assoc [
-          ("nodes", `List added_nodes) ;
-          ("deps", `List added_deps)
-        ]) ;
-      ("sub", `List removed_nodes)]
-end
-
-let ouptput_to_json out_channel g =
-  let json = JsonPrinter.output_graph g in
-  Yojson.Basic.to_channel out_channel json
-
-let to_json g =
-  JsonPrinter.output_graph g
-
-let diff_to_json g diff =
-  JsonPrinter.output_diff g diff
diff --git a/src/plugins/dive/dive_graph.mli b/src/plugins/dive/dive_graph.mli
index 987080b02037a73ce3471f257c7060174d075755..2f3e9635f8a96b2a498e8575272b8a9689125de9 100644
--- a/src/plugins/dive/dive_graph.mli
+++ b/src/plugins/dive/dive_graph.mli
@@ -42,8 +42,8 @@ val update_node_values : node ->
   typ:Cil_types.typ -> cvalue:Cvalue.V.t -> taint:Eva.Results.taint option ->
   unit
 
-val create_dependency : t -> Cil_types.kinstr ->
-  node -> dependency_kind -> node -> unit
+val create_dependency : t -> origin:origin -> kind:dependency_kind ->
+  node -> node -> node * dependency * node
 
 val remove_dependency : t -> node * dependency * node -> unit
 val remove_dependencies : t -> node -> unit
@@ -52,8 +52,4 @@ val find_independant_nodes : t -> node list -> node list
 val bfs : ?iter_succ:((node -> unit) -> t -> node -> unit) -> ?limit:int ->
   t -> node list -> node list
 
-val ouptput_to_dot : out_channel -> t -> unit
-val ouptput_to_json : out_channel -> t -> unit
-
-val to_json : t -> Json.t
-val diff_to_json : t -> graph_diff -> Json.t
+val output_to_dot : out_channel -> t -> unit
diff --git a/src/plugins/dive/dive_types.ml b/src/plugins/dive/dive_types.ml
index c71f7f375cd6f901e8c23e25539249b2a41bbdac..b38f5e975a499d4cf08cf055547cbef0c3e34d7d 100644
--- a/src/plugins/dive/dive_types.ml
+++ b/src/plugins/dive/dive_types.ml
@@ -23,8 +23,8 @@
 type node_kind =
   | Scalar of Cil_types.varinfo * Cil_types.typ * Cil_types.offset
   | Composite of Cil_types.varinfo
-  | Scattered of Cil_types.lval * Cil_types.kinstr
-  | Unknown of Cil_types.lval * Cil_types.kinstr
+  | Scattered of Cil_types.lval * Cil_types.stmt
+  | Unknown of Cil_types.lval * Cil_types.stmt
   | Alarm of Cil_types.stmt * Alarms.alarm
   | AbsoluteMemory
   | String of int * Base.cstring
@@ -46,6 +46,8 @@ type node_range =
 
 type computation = NotDone | Partial of (unit Seq.t) | Done
 
+type origin = Studia.Writes.t
+
 type node = {
   node_key : int;
   node_kind : node_kind;
@@ -57,7 +59,7 @@ type node = {
   mutable node_taint : Eva.Results.taint option;
   mutable node_writes_computation : computation;
   mutable node_reads_computation : computation;
-  mutable node_writes_stmts : Cil_types.stmt list;
+  mutable node_writes : origin list;
 }
 
 type dependency_kind = Callee | Data | Address | Control | Composition
@@ -65,7 +67,7 @@ type dependency_kind = Callee | Data | Address | Control | Composition
 type dependency = {
   dependency_key : int;
   dependency_kind : dependency_kind;
-  mutable dependency_origins : Cil_types.stmt list;
+  mutable dependency_origins : origin list;
 }
 
 type graph_diff = {
diff --git a/src/plugins/dive/main.ml b/src/plugins/dive/main.ml
index 86d8e2d5393c6c7f224a152c1b775cc6b03b9b69..6c81b013f84c8a11d4aea07b9852af7cc1ca04f4 100644
--- a/src/plugins/dive/main.ml
+++ b/src/plugins/dive/main.ml
@@ -24,8 +24,8 @@ type format = Dot | Json
 
 let output format context filename =
   let output_function = match format with
-    | Dot -> Dive_graph.ouptput_to_dot
-    | Json -> Dive_graph.ouptput_to_json
+    | Dot -> Dive_graph.output_to_dot
+    | Json -> Server_interface.output_to_json
   in
   Self.result "output to %a" Filepath.Normalized.pretty filename;
   let out_channel = open_out (filename:>string) in
@@ -35,6 +35,8 @@ let output format context filename =
 let main () =
   if not (Self.FromBases.is_empty () &&
           Self.FromFunctionAlarms.is_empty ()) then begin
+    (* Make sure Eva is computed *)
+    Eva.Analysis.compute ();
     (* Create the initial graph  *)
     let context = Context.create () in
     (* Handle parameters *)
diff --git a/src/plugins/dive/node_kind.ml b/src/plugins/dive/node_kind.ml
index 1d46ba6136ea6653d82e21a4d3f5fcc9ff9a3f7f..de501c05d61436230f0a301480d9dbf678f1a967 100644
--- a/src/plugins/dive/node_kind.ml
+++ b/src/plugins/dive/node_kind.ml
@@ -51,12 +51,12 @@ struct
     | Composite vi1, Composite vi2 -> Varinfo.compare vi1 vi2
     | Composite _, _ -> 1
     | _, Composite _ -> -1
-    | Scattered (lv1,ki1), Scattered (lv2,ki2) ->
-      LvalStructEq.compare lv1 lv2 <?> (Kinstr.compare, ki1, ki2)
+    | Scattered (lv1,stmt1), Scattered (lv2,stmt2) ->
+      LvalStructEq.compare lv1 lv2 <?> (Stmt.compare, stmt1, stmt2)
     | Scattered _, _ -> 1
     | _, Scattered _ -> -1
-    | Unknown (lv1,ki1), Unknown (lv2,ki2) ->
-      LvalStructEq.compare lv1 lv2 <?> (Kinstr.compare, ki1, ki2)
+    | Unknown (lv1,stmt1), Unknown (lv2,stmt2) ->
+      LvalStructEq.compare lv1 lv2 <?> (Stmt.compare, stmt1, stmt2)
     | Unknown _, _ -> 1
     | _, Unknown _ -> -1
     | Alarm (stmt1, alarm1), Alarm (stmt2, alarm2) ->
@@ -82,10 +82,10 @@ struct
     | Scalar (vi1, _, offset1), Scalar (vi2, _, offset2) ->
       Varinfo.equal vi1 vi2 && OffsetStructEq.equal offset1 offset2
     | Composite vi1, Composite vi2 -> Varinfo.equal vi1 vi2
-    | Scattered (lv1, ki1), Scattered (lv2, ki2) ->
-      LvalStructEq.equal lv1 lv2 && Kinstr.equal ki1 ki2
-    | Unknown (lv1, ki1), Unknown (lv2, ki2) ->
-      LvalStructEq.equal lv1 lv2 && Kinstr.equal ki1 ki2
+    | Scattered (lv1, stmt1), Scattered (lv2, stmt2) ->
+      LvalStructEq.equal lv1 lv2 && Stmt.equal stmt1 stmt2
+    | Unknown (lv1, stmt1), Unknown (lv2, stmt2) ->
+      LvalStructEq.equal lv1 lv2 && Stmt.equal stmt1 stmt2
     | Alarm (stmt1, alarm1), Alarm (stmt2, alarm2) ->
       Stmt.equal stmt1 stmt2 && Alarms.equal alarm1 alarm2
     | AbsoluteMemory, AbsoluteMemory -> true
@@ -99,10 +99,10 @@ struct
     | Scalar (vi, _, offset) ->
       Hashtbl.hash (1, Varinfo.hash vi, OffsetStructEq.hash offset)
     | Composite vi -> Hashtbl.hash (2, Varinfo.hash vi)
-    | Scattered (lv, ki) ->
-      Hashtbl.hash (3, LvalStructEq.hash lv, Kinstr.hash ki)
-    | Unknown (lv, ki) ->
-      Hashtbl.hash (4, LvalStructEq.hash lv, Kinstr.hash ki)
+    | Scattered (lv, stmt) ->
+      Hashtbl.hash (3, LvalStructEq.hash lv, Stmt.hash stmt)
+    | Unknown (lv, stmt) ->
+      Hashtbl.hash (4, LvalStructEq.hash lv, Stmt.hash stmt)
     | Alarm (stmt, alarm) ->
       Hashtbl.hash (5, Stmt.hash stmt, Alarms.hash alarm)
     | AbsoluteMemory -> 6
diff --git a/src/plugins/dive/self.ml b/src/plugins/dive/self.ml
index 4e3bb2c1eef4774d191c2084ee7107b65cf29c20..df6cbfc9216ce23512ee8496d27abe6913b1116e 100644
--- a/src/plugins/dive/self.ml
+++ b/src/plugins/dive/self.ml
@@ -75,9 +75,9 @@ struct
         with Not_found ->
           raise (Cannot_build ("no function '" ^ function_name ^ "'"))
       in
-      try Globals.Vars.find_from_astinfo variable_name (VLocal kf)
+      try Globals.Vars.find_from_astinfo variable_name (Whole_function kf)
       with Not_found ->
-      try Globals.Vars.find_from_astinfo variable_name (VFormal kf)
+      try Globals.Vars.find_from_astinfo variable_name (Formal kf)
       with Not_found ->
         raise (Cannot_build ("no variable '" ^ variable_name ^ "' in function "
                              ^ function_name))
diff --git a/src/plugins/dive/server_interface.ml b/src/plugins/dive/server_interface.ml
index dab161a0c2940d6df6015dad2930651fbee98386..e3fcfb5515fe51d96dd70148975d4b7677f555a4 100644
--- a/src/plugins/dive/server_interface.ml
+++ b/src/plugins/dive/server_interface.ml
@@ -25,225 +25,417 @@ open Data
 open Dive_types
 
 let package = Package.package ~plugin:"dive" ~title:"Dive Services" ()
+let declare name ?(descr = name) =
+  Data.declare ~package ~name ~descr:(Markdown.plain descr)
 
+module Enum (X: sig type t end) =
+struct
+  include Enum
+  let dictionary: X.t dictionary = Enum.dictionary ()
+  let tag name descr = Enum.tag ~name ~descr:(Markdown.plain descr) dictionary
+  let publish lookup name descr =
+    set_lookup dictionary lookup;
+    Request.dictionary ~package ~name ~descr:(Markdown.plain descr) dictionary
+end
 
-(* -------------------------------------------------------------------------- *)
-(* --- State handling                                                     --- *)
-(* -------------------------------------------------------------------------- *)
-
-(* TODO: project state *)
-let get_context =
-  let context = ref None in
-  fun () ->
-    match !context with
-    | Some c -> c
-    | None ->
-      if Eva.Analysis.is_computed () then
-        let c = Context.create () in
-        context := Some c;
-        c
-      else
-        Server.Data.failure "Eva analysis not computed"
-
-
-let global_window = ref {
-    perception = { backward = Some 2 ; forward = Some 1 };
-    horizon = { backward = None ; forward = None };
-  }
+module Record () =
+struct
+  include Record
+  type record
+  let record : record Record.signature = Record.signature ()
+  let field name ?(descr = name) =
+    Record.field record ~name ~descr:(Markdown.plain descr)
+  let option name ?(descr = name) =
+    Record.option record ~name ~descr:(Markdown.plain descr)
+  let publish ?descr name =
+    let descr = Option.map Markdown.plain descr in
+    Record.publish record ~package ~name ?descr
+end
 
 
 (* -------------------------------------------------------------------------- *)
 (* --- Data types                                                         --- *)
 (* -------------------------------------------------------------------------- *)
 
-module Range : Data.S with type t = int option range =
-struct
-  type t = int option range
-  let name = "range"
-  let descr = Markdown.plain "Parametrization of the exploration range."
-  let sign : t Record.signature = Record.signature ()
+let stmt_to_location stmt =
+  let kf = Kernel_function.find_englobing_kf stmt in
+  (kf, Printer_tag.PStmtStart (kf, stmt))
+
+let origin_to_locations = function
+  | Studia.Writes.Assign s
+  | CallDirect s -> [stmt_to_location s]
+  | CallIndirect _s -> []
+  | GlobalInit (_vi, _init) -> []
+  | FormalInit (_vi, callsites) ->
+    List.concat_map (fun (_,l) -> List.map stmt_to_location l) callsites
 
-  module Fields =
-  struct
-    let backward = Record.option sign
-        ~name:"backward"
-        ~descr:(Markdown.plain "range for the write dependencies")
-        (module (Jint))
 
-    let forward = Record.option sign
-        ~name:"forward"
-        ~descr:(Markdown.plain "range for the read dependencies")
-        (module (Jint))
-  end
+module Range : Data.S with type t = int option range =
+struct
+  include Record ()
 
-  module Record = (val Record.publish ~package ~name ~descr sign)
+  let backward =
+    option "backward" ~descr:"range for the write dependencies" jint
+  let forward =
+    option "forward" ~descr:"range for the read dependencies" jint
 
-  let jtype = Record.jtype
+  let descr = "Parametrization of the exploration range."
+  include (val publish "range" ~descr)
+  type t = int option range
 
-  let to_json r =
-    Record.default |>
-    Record.set Fields.backward r.backward |>
-    Record.set Fields.forward r.forward |>
-    Record.to_json
+  let to_json r=
+    default |>
+    set backward r.backward |>
+    set forward r.forward |>
+    to_json
 
   let of_json js =
-    let r = Record.of_json js in
-    {
-      backward = Record.get Fields.backward r;
-      forward = Record.get Fields.forward r;
-    }
+    let r = of_json js in
+    { backward = get backward r; forward = get forward r; }
 end
 
 
 module Window : Data.S with type t = window =
 struct
-  type t = window
-  let name = "explorationWindow"
-  let descr = Markdown.plain "Global parametrization of the exploration."
-  let sign : t Record.signature = Record.signature ()
-
-  module Fields =
-  struct
-    let perception = Record.field sign
-        ~name:"perception"
-        ~descr:(Markdown.plain "how far dive will explore from root nodes ; \
-                                must be a finite range")
-        (module Range)
+  include Record ()
 
-    let horizon = Record.field sign
-        ~name:"horizon"
-        ~descr:(Markdown.plain "range beyond which the nodes must be hidden")
-        (module Range)
-  end
+  let perception =
+    let descr = "how far dive will explore from root nodes ; \
+                 must be a finite range" in
+    field "perception" ~descr (module Range)
 
-  module Record = (val Record.publish ~package ~name ~descr sign)
+  let horizon =
+    let descr = "range beyond which the nodes must be hidden" in
+    field "horizon" ~descr (module Range)
 
-  let jtype = Record.jtype
+  let descr = "Global parametrization of the exploration."
+  include (val publish "explorationWindow" ~descr)
+  type t = window
 
   let to_json w =
-    Record.default |>
-    Record.set Fields.perception w.perception |>
-    Record.set Fields.horizon w.horizon |>
-    Record.to_json
+    default |>
+    set perception w.perception |>
+    set horizon w.horizon |>
+    to_json
 
   let of_json js =
-    let r = Record.of_json js in
-    {
-      perception = Record.get Fields.perception r;
-      horizon = Record.get Fields.horizon r;
-    }
+    let r = of_json js in
+    { perception = get perception r; horizon = get horizon r; }
 end
 
 
 module NodeId =
 struct
-  type t = node
-  let name = "nodeId"
-  let descr = Markdown.plain "A node identifier in the graph"
-
-  let jtype = Data.declare ~package ~name ~descr Data.Jint.jtype
-
-  let _to_json node =
-    `Int node.node_key
-
-  let of_json json =
-    let node_key = Data.Jint.of_json json in
-    try
-      Context.find_node (get_context ()) node_key
-    with Not_found ->
-      Data.failure "no node '%d' in the current graph" node_key
+  include Data.Jint
+  let jtype = declare "nodeId" ~descr:"A node identifier in the graph" jtype
 end
 
 module Callsite =
 struct
-  let name = "callsite"
-  let descr = Markdown.plain "A callsite"
-  let jtype = Data.declare ~package ~name ~descr (Jrecord [
+  type t = Cil_types.kernel_function * Cil_types.kinstr
+  let jtype = declare "callsite" (Jrecord [
       "fun", Jstring;
-      "instr", Junion [ Jnumber ; Jstring ];
+      "instr", Junion [ Jnumber ; Jtag "global" ];
     ])
+
+  let output_kinstr = function
+    | Cil_types.Kglobal -> `String "global"
+    | Cil_types.Kstmt stmt -> `Int stmt.sid
+
+  let to_json (kf, kinstr) =
+    `Assoc [
+      ("fun", `String (Kernel_function.get_name kf)) ;
+      ("instr", output_kinstr kinstr) ;
+    ]
+
+  let of_json _ = Data.failure "Callsite.of_json not implemented"
 end
 
 module Callstack =
 struct
-  let name = "callstack"
-  let descr = Markdown.plain "The callstack context for a node"
-  let jtype = Data.declare ~package ~name ~descr (Jarray Callsite.jtype)
+  include Data.Jlist (Callsite)
+  let descr = "The callstack context for a node"
+  let jtype = declare "callstack" ~descr jtype
 end
 
 module NodeLocality =
 struct
-  let name = "nodeLocality"
-  let descr = Markdown.plain "The description of a node locality"
-  let jtype = Data.declare ~package ~name ~descr (Jrecord [
-      "file", Jstring;
-      "callstack", Joption (Callstack.jtype)
-    ])
+  include Record ()
+
+  let file = field "file" jstring
+  let callstack = option "callstack" (module Callstack)
+
+  let descr = "The description of a node locality"
+  include (val publish "nodeLocality" ~descr)
+  type t = node_locality
+
+  let to_json t =
+    let to_option = function [] -> None | l -> Some l in
+    default |>
+    set file t.loc_file |>
+    set callstack (to_option t.loc_callstack) |>
+    to_json
+
+  let of_json js =
+    let r = of_json js in
+    { loc_file = get file r ;
+      loc_callstack = Option.value ~default:[] (get callstack r) }
+end
+
+module NodeKind = struct
+  include Enum (struct type t = node_kind end)
+
+  let scalar =    tag "scalar"    "a single memory cell"
+  let composite = tag "composite" "a memory bloc containing cells"
+  let scattered = tag "scattered" "a set of memory locations designated by \
+                                   an lvalue"
+  let unknown =   tag "unknown"   "an unresolved memory location"
+  let alarm =     tag "alarm"     "an alarm emitted by Frama-C"
+  let absolute =  tag "absolute"  "a memory location designated by a range \
+                                   of adresses"
+  let string =    tag "string"    "a string literal"
+  let error =     tag "error"     "a placeholder node when an error prevented \
+                                   the generation process"
+  let const =     tag "const"     "a numeric constant literal"
+
+  let lookup = function
+    | Scalar _ -> scalar
+    | Composite _ -> composite
+    | Scattered _ -> scattered
+    | Unknown _ -> unknown
+    | Alarm _ -> alarm
+    | AbsoluteMemory -> absolute
+    | String _ -> string
+    | Const _ -> const
+    | Error _ -> error
+
+  include (val publish lookup "nodeKind" "The nature of a node")
+end
+
+module Taint = struct
+  include Enum (struct type t = Eva.Results.taint end)
+
+  let untainted = tag "untainted" "not tainted by anything"
+  let indirect = tag "indirect" "tainted by control"
+  let direct = tag "direct" "tainted by data"
+
+  let lookup = function
+    | Eva.Results.Direct -> direct
+    | Indirect -> indirect
+    | Untainted -> untainted
+
+  include (val publish lookup "taint" "Taint of a memory location")
+end
+
+module Computation = struct
+  include Enum (struct type t = computation end)
+
+  let yes = tag "yes" "all dependencies have been computed"
+  let partial = tag "partial" "some dependencies have been explored"
+  let no = tag "no" "dependencies have not been computed"
+
+  let lookup = function
+    | Done -> yes
+    | Partial _ -> partial
+    | NotDone -> no
+
+  let descr = "The computation state of a node read or write dependencies"
+  include (val publish lookup "exploration" descr)
+end
+
+module NodeSpecialRange = struct
+  include Enum (struct type t = node_range end)
+
+  let empty = tag "empty" "no value ever computed for this node"
+  let singleton = tag "singleton" "this node can only have one value"
+  let wide = tag "wide" "this node can take almost all values of its type"
+
+  let lookup = function
+    | Empty -> empty
+    | Singleton -> singleton
+    | Wide -> wide
+    | Normal _ -> raise Not_found
+
+  let descr = "A qualitative description of the range of values \
+               that this node can take."
+
+  include (val publish lookup "nodeSpecialRange" descr)
+end
+
+module NodeRange = struct
+  type t = node_range
+  let descr = "A qualitative or quantitative description of the range of \
+               values that this node can take."
+  let jtype = declare "nodeRange" ~descr
+      (Junion [ Jnumber ; NodeSpecialRange.jtype ])
+
+  let to_json = function
+    | Normal range_grade -> `Int range_grade
+    | range -> NodeSpecialRange.to_json range
+
+  let of_json _ = Data.failure "NodeRange.of_json not implemented"
 end
 
 module Node =
 struct
-  let name = "node"
-  let descr = Markdown.plain "A graph node"
-  let jtype = Data.declare ~package ~name ~descr (Jrecord [
-      "id", NodeId.jtype;
-      "label", Jstring;
-      "kind", Jstring;
-      "locality", NodeLocality.jtype;
-      "is_root", Jboolean;
-      "backward_explored", Jstring;
-      "forward_explored", Jstring;
-      "writes", Jarray Kernel_ast.Location.jtype;
-      "values", Joption Jstring;
-      "range", Junion [ Jnumber ; Jstring ];
-      "type", Joption Jstring;
-      "taint", Joption (Junion [
-          Jtag "direct"; Jtag "indirect"; Jtag "untainted"])
-    ])
+  include Record ()
+
+  let id = field "id" (module NodeId)
+  let label = field "label" jstring
+  let nkind = field "nkind" (module NodeKind)
+  let locality = field "locality" (module NodeLocality)
+  let is_root = field "is_root" jbool
+  let backward_explored = field "backward_explored" (module Computation)
+  let forward_explored = field "forward_explored" (module Computation)
+  let writes = field "writes" (module Jlist (Kernel_ast.Location))
+  let values = field "values" (joption jstring)
+  let range = field "range" (module NodeRange)
+  let typ = option "type" jstring
+  let taint = option "taint" (module Taint)
+
+  include (val publish "node")
+
+  let node_type node =
+    match Node_kind.to_lval node.node_kind with
+    | None -> None
+    | Some lval ->
+      let typ = Cil.typeOfLval lval in
+      Some (Pretty_utils.to_string Cil_printer.pp_typ typ)
+
+  let to_json node =
+    default |>
+    set id node.node_key |>
+    set label (Pretty_utils.to_string Node_kind.pretty node.node_kind) |>
+    set nkind node.node_kind |>
+    set locality node.node_locality |>
+    set is_root node.node_is_root |>
+    set backward_explored node.node_writes_computation |>
+    set forward_explored node.node_reads_computation |>
+    set writes (List.concat_map origin_to_locations node.node_writes) |>
+    set values
+      (Option.map (Pretty_utils.to_string Cvalue.V.pretty) node.node_values) |>
+    set range node.node_range |>
+    set typ (node_type node) |>
+    set taint node.node_taint |>
+    to_json
 end
 
 module Dependency =
 struct
-  let name = "dependency"
-  let descr = Markdown.plain "The dependency between two nodes"
-  let jtype = Data.declare ~package ~name ~descr (Jrecord [
-      "id", Jnumber ;
-      "src", NodeId.jtype ;
-      "dst", NodeId.jtype ;
-      "kind", Jstring ;
-      "origins", Jarray Kernel_ast.Location.jtype
-    ])
+  include Record ()
+
+  let id = field "id" jint
+  let src = field "src" (module NodeId)
+  let dst = field "dst" (module NodeId)
+  let dkind = field "dkind" jstring
+  let origins = field "origins" (module Jlist (Kernel_ast.Location))
+
+  include (val publish "dependency" ~descr:"The dependency between two nodes")
+
+  let dep_kind = function
+    | Callee -> "callee"
+    | Data -> "data"
+    | Address -> "addr"
+    | Control -> "ctrl"
+    | Composition -> "comp"
+
+  let to_json (n1, dep, n2) =
+    default |>
+    set id dep.dependency_key |>
+    set src n1.node_key |>
+    set dst n2.node_key |>
+    set dkind  (dep_kind dep.dependency_kind) |>
+    set origins (List.concat_map origin_to_locations dep.dependency_origins) |>
+    to_json
 end
 
-module Graph =
+module Element =
 struct
-  type t = Dive_graph.t
-  let name = "graphData"
-  let descr = Markdown.plain "The whole graph being built"
-  let jtype = Data.declare ~package ~name ~descr (Jrecord [
-      "nodes", Jarray Node.jtype;
-      "deps", Jarray Dependency.jtype
-    ])
+  type t = Context.element = Node of node | Edge of (node * dependency * node)
+  let descr = "A graph element, either a node or a dependency"
+  let jtype = declare "element" ~descr (Junion [Node.jtype ; Dependency.jtype])
 
-  let to_json = Dive_graph.to_json
+  let to_json = function
+    | Node v -> Node.to_json v
+    | Edge edge -> Dependency.to_json edge
 end
 
 
-module GraphDiff =
+(* -------------------------------------------------------------------------- *)
+(* --- State handling                                                     --- *)
+(* -------------------------------------------------------------------------- *)
+
+let global_window = ref {
+    perception = { backward = Some 2 ; forward = Some 1 };
+    horizon = { backward = None ; forward = None };
+  }
+
+let get_context = (* TODO: projectify ? *)
+  let context = Context.create () in
+  fun () ->
+    if Eva.Analysis.is_computed () then
+      context
+    else
+      Server.Data.failure "Eva analysis not computed"
+
+let vertices g = Dive_graph.fold_vertex (fun n acc -> n ::acc) g []
+let edges g = Dive_graph.fold_edges_e (fun d acc -> d ::acc) g []
+
+let output_graph g =
+  `Assoc [
+    ("nodes", `List (List.map Node.to_json (vertices g))) ;
+    ("deps", `List (List.map Dependency.to_json (edges g)))
+  ]
+
+let output_to_json out_channel g =
+  let json = output_graph g in
+  Yojson.Basic.to_channel out_channel json
+
+module Graph =
 struct
-  type t = Dive_graph.t * graph_diff
-  let name = "diffData"
-  let descr = Markdown.plain "Graph differences from the last action."
-  let jtype = Data.declare ~package ~name ~descr (Jrecord [
-      "root", Joption NodeId.jtype;
-      "add", Jrecord [
-        "nodes", Jarray Node.jtype;
-        "deps", Jarray Dependency.jtype
-      ];
-      "sub", Jarray NodeId.jtype
-    ])
+  let name = "graph"
+  let model = States.model ()
+  let descr = Markdown.plain "The graph being built as a set of vertices and \
+                              edges"
+
+  let key = function
+    | Element.Node v -> Format.sprintf "n%d" v.node_key
+    | Edge (_,dep,_) -> Format.sprintf "d%d" dep.dependency_key
+
+  let () = States.column model ~name:"element"
+      ~descr:(Markdown.plain "a graph element")
+      ~data:(module Element)
+      ~get:(fun el -> el)
+
+
+  let iter f =
+    let context = get_context () in
+    let graph = Context.get_graph context in
+    Dive_graph.iter_vertex (fun v -> f (Element.Node v)) graph;
+    Dive_graph.iter_edges_e (fun e -> f (Element.Edge e)) graph
+
+  let _array =
+    let hook f =
+      fun g -> f (get_context ()) g
+    in
+    States.register_array ~package ~name ~descr ~key ~iter model
+      ~add_update_hook:(hook Context.set_update_hook)
+      ~add_remove_hook:(hook Context.set_remove_hook)
+      ~add_reload_hook:(hook Context.set_clear_hook)
+end
+
 
-  let to_json = fun (g,d) -> Dive_graph.diff_to_json g d
+module NodeId' =
+struct
+  type t = node
+  let jtype = NodeId.jtype
+  let to_json node = NodeId.to_json node.node_key
+  let of_json json =
+    let node_key = Data.Jint.of_json json in
+    try
+      Context.find_node (get_context ()) node_key
+    with Not_found ->
+      Data.failure "no node '%d' in the current graph" node_key
 end
 
 
@@ -251,26 +443,19 @@ end
 (* --- Actions                                                            --- *)
 (* -------------------------------------------------------------------------- *)
 
-let result context last_root =
-  let diff = Context.take_last_diff context in
-  Context.get_graph context, { diff with last_root }
-
-let finalize' context node_opt =
-  begin match node_opt with
-    | None -> ()
-    | Some node ->
-      let may_explore f =
-        Option.iter (fun depth -> f ~depth context node)
-      in
-      may_explore Build.explore_backward !global_window.perception.backward;
-      may_explore Build.explore_forward !global_window.perception.forward;
-      let horizon = !global_window.horizon in
-      if Option.is_some horizon.forward ||
-         Option.is_some horizon.backward
-      then
-        Build.reduce_to_horizon context horizon node
-  end;
-  result context node_opt
+let finalize' context = function
+  | None -> ()
+  | Some node ->
+    let may_explore f =
+      Option.iter (fun depth -> f ~depth context node)
+    in
+    may_explore Build.explore_backward !global_window.perception.backward;
+    may_explore Build.explore_forward !global_window.perception.forward;
+    let horizon = !global_window.horizon in
+    if Option.is_some horizon.forward ||
+       Option.is_some horizon.backward
+    then
+      Build.reduce_to_horizon context horizon node
 
 let finalize context node =
   finalize' context (Some node)
@@ -281,12 +466,6 @@ let () = Request.register ~package
     ~input:(module Window) ~output:(module Data.Junit)
     (fun window -> global_window := window)
 
-let () = Request.register ~package
-    ~kind:`GET ~name:"graph"
-    ~descr:(Markdown.plain "Retrieve the whole graph")
-    ~input:(module Data.Junit) ~output:(module Graph)
-    (fun () -> Context.get_graph (get_context ()))
-
 let () = Request.register ~package
     ~kind:`EXEC ~name:"clear"
     ~descr:(Markdown.plain "Erase the graph and start over with an empty one")
@@ -296,16 +475,18 @@ let () = Request.register ~package
 let () = Request.register ~package
     ~kind:`EXEC ~name:"add"
     ~descr:(Markdown.plain "Add a node to the graph")
-    ~input:(module Kernel_ast.Marker) ~output:(module GraphDiff)
+    ~input:(module Kernel_ast.Marker) ~output:(module Joption (NodeId'))
     begin fun loc ->
       let context = get_context () in
-      finalize' context (Build.add_localizable context loc)
+      let node = Build.add_localizable context loc in
+      finalize' context node;
+      node
     end
 
 let () = Request.register ~package
     ~kind:`EXEC ~name:"explore"
     ~descr:(Markdown.plain "Explore the graph starting from an existing vertex")
-    ~input:(module NodeId) ~output:(module GraphDiff)
+    ~input:(module NodeId') ~output:(module Data.Junit)
     begin fun node ->
       let context = get_context () in
       Build.show context node;
@@ -315,7 +496,7 @@ let () = Request.register ~package
 let () = Request.register ~package
     ~kind:`EXEC ~name:"show"
     ~descr:(Markdown.plain "Show the dependencies of an existing vertex")
-    ~input:(module NodeId) ~output:(module GraphDiff)
+    ~input:(module NodeId') ~output:(module Data.Junit)
     begin fun node ->
       let context = get_context () in
       Build.show context node;
@@ -326,7 +507,7 @@ let () = Request.register ~package
 let () = Request.register ~package
     ~kind:`EXEC ~name:"hide"
     ~descr:(Markdown.plain "Hide the dependencies of an existing vertex")
-    ~input:(module NodeId) ~output:(module GraphDiff)
+    ~input:(module NodeId') ~output:(module Data.Junit)
     begin fun node ->
       let context = get_context () in
       Build.hide context node;
diff --git a/src/plugins/dive/server_interface.mli b/src/plugins/dive/server_interface.mli
index bd656c9049e55b9db813ea3a69c9d0538ce4a763..d8adab7ed6a4aef38c4fa25a4bfcfdf3b0811aad 100644
--- a/src/plugins/dive/server_interface.mli
+++ b/src/plugins/dive/server_interface.mli
@@ -21,3 +21,5 @@
 (**************************************************************************)
 
 (* Dive API for the server. Nothing is exported. *)
+
+val output_to_json: out_channel -> Dive_graph.t -> unit
diff --git a/src/plugins/dive/tests/dive/oracle/assigned_param.dot b/src/plugins/dive/tests/dive/oracle/assigned_param.dot
index a1190d2d94fd0e19e93369c4f7543bcf51d966d6..dbf37f6f407a6e3967e6f8f52940fa21910a2279 100644
--- a/src/plugins/dive/tests/dive/oracle/assigned_param.dot
+++ b/src/plugins/dive/tests/dive/oracle/assigned_param.dot
@@ -3,21 +3,21 @@ digraph G {
        style="filled,bold", ];
   cp3 [label=<x>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
        style="filled", ];
-  cp5 [label=<x>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
+  cp5 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
        style="filled", ];
-  cp7 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
+  cp7 [label=<x>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
        style="filled", ];
   cp9 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
        style="filled", ];
   
-  subgraph cluster_cs_1 { label=<main>; cp9;cp5;cp2;
-    subgraph cluster_cs_2 { label=<f>; cp7;cp3;
+  subgraph cluster_cs_1 { label=<main>; cp9;cp7;cp2;
+    subgraph cluster_cs_2 { label=<f>; cp5;cp3;
        };
      };
   
   cp3 -> cp2;
   cp5 -> cp3;
   cp7 -> cp3;
-  cp9 -> cp7;
+  cp9 -> cp5;
   
   }
\ No newline at end of file
diff --git a/src/plugins/dive/tests/dive/oracle/callstack_global.dot b/src/plugins/dive/tests/dive/oracle/callstack_global.dot
index d2245d10a588309fb482b7056f5153ce5016c37c..927402ef746431e2a2fddfc9e44d18404d0fcf87 100644
--- a/src/plugins/dive/tests/dive/oracle/callstack_global.dot
+++ b/src/plugins/dive/tests/dive/oracle/callstack_global.dot
@@ -13,14 +13,15 @@ digraph G {
         style="filled", ];
   cp15 [label=<x>, shape=box, fillcolor="#EEFFEE", color="#004400",
         style="filled", ];
-  cp17 [label=<x2>, shape=box, fillcolor="#AACCFF", color="#88AAFF",
-        style="filled", ];
+  cp17 [label=<0>, shape=ellipse, ];
   cp19 [label=<x1>, shape=box, fillcolor="#AACCFF", color="#88AAFF",
         style="filled", ];
-  cp21 [label=<39>, shape=ellipse, ];
+  cp21 [label=<x2>, shape=box, fillcolor="#AACCFF", color="#88AAFF",
+        style="filled", ];
   cp23 [label=<3>, shape=ellipse, ];
+  cp25 [label=<39>, shape=ellipse, ];
   
-  subgraph cluster_cs_1 { label=<main>; cp23;cp21;cp19;cp17;cp5;cp3;cp2;
+  subgraph cluster_cs_1 { label=<main>; cp25;cp23;cp21;cp19;cp5;cp3;cp2;
     subgraph cluster_cs_2 { label=<f>; cp7;
        };
     subgraph cluster_cs_3 { label=<f>; cp9;
@@ -28,7 +29,7 @@ digraph G {
      };
   subgraph cluster_cs_4 { label=<f>; cp15;
      };
-  subgraph cluster_file_1 { label=<callstack_global.i>; cp11;
+  subgraph cluster_file_1 { label=<callstack_global.i>; cp17;cp11;
      };
   
   cp3 -> cp2;
@@ -39,9 +40,10 @@ digraph G {
   cp11 -> cp9;
   cp11 -> cp11;
   cp15 -> cp11;
-  cp17 -> cp15;
+  cp17 -> cp11;
   cp19 -> cp15;
-  cp21 -> cp17;
+  cp21 -> cp15;
   cp23 -> cp19;
+  cp25 -> cp21;
   
   }
\ No newline at end of file
diff --git a/src/plugins/dive/tests/dive/oracle/callstack_strategy.dot b/src/plugins/dive/tests/dive/oracle/callstack_strategy.dot
index 1944fac8cbf2e0aeb6d60f86d28a5cb43919f25e..f343686a117e0a25a97402d5b40f0ebad3efc64f 100644
--- a/src/plugins/dive/tests/dive/oracle/callstack_strategy.dot
+++ b/src/plugins/dive/tests/dive/oracle/callstack_strategy.dot
@@ -5,15 +5,15 @@ digraph G {
        style="filled", ];
   cp5 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
        style="filled", ];
-  cp7 [label=<x>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
+  cp7 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
        style="filled", ];
-  cp9 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
+  cp9 [label=<x>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
        style="filled", ];
   cp11 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
         style="filled", ];
-  cp13 [label=<a>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
+  cp13 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
         style="filled", ];
-  cp15 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
+  cp15 [label=<a>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
         style="filled", ];
   cp18 [label=<x>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
         style="filled", ];
@@ -22,13 +22,13 @@ digraph G {
     subgraph cluster_cs_4 { label=<f>; cp11;
        };
      };
-  subgraph cluster_cs_2 { label=<i>; cp7;
-     };
-  subgraph cluster_cs_3 { label=<h>; cp18;cp9;
-    subgraph cluster_cs_6 { label=<f>; cp15;
+  subgraph cluster_cs_2 { label=<h>; cp18;cp7;
+    subgraph cluster_cs_5 { label=<f>; cp13;
        };
      };
-  subgraph cluster_cs_5 { label=<main>; cp13;
+  subgraph cluster_cs_3 { label=<i>; cp9;
+     };
+  subgraph cluster_cs_6 { label=<main>; cp15;
      };
   
   cp3 -> cp2;
@@ -38,8 +38,8 @@ digraph G {
   cp9 -> cp3;
   cp11 -> cp5;
   cp13 -> cp7;
-  cp13 -> cp18;
   cp15 -> cp9;
-  cp18 -> cp15;
+  cp15 -> cp18;
+  cp18 -> cp13;
   
   }
\ No newline at end of file
diff --git a/src/plugins/dive/tests/dive/oracle/global.dot b/src/plugins/dive/tests/dive/oracle/global.dot
index 36c6ca1aa9f8d8457b593fa6eccfe780127a22bc..2659479de44b35d430becb1153d31d1a0c3dde6d 100644
--- a/src/plugins/dive/tests/dive/oracle/global.dot
+++ b/src/plugins/dive/tests/dive/oracle/global.dot
@@ -7,15 +7,17 @@ digraph G {
        style="filled", ];
   cp7 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
        style="filled", ];
+  cp9 [label=<0>, shape=ellipse, ];
   
   subgraph cluster_cs_1 { label=<main>; cp7;cp5;cp2;
      };
-  subgraph cluster_file_1 { label=<global.i>; cp3;
+  subgraph cluster_file_1 { label=<global.i>; cp9;cp3;
      };
   
   cp3 -> cp2;
   cp5 -> cp2;
   cp5 -> cp7;
   cp7 -> cp3;
+  cp9 -> cp3;
   
   }
\ No newline at end of file
diff --git a/src/plugins/dive/tests/dive/oracle/unfocused_callers.dot b/src/plugins/dive/tests/dive/oracle/unfocused_callers.dot
index 1978773631238f75819acf83686dc50b242d2366..c1212e05cefdb363f882f5cb34a1b977b4c942a1 100644
--- a/src/plugins/dive/tests/dive/oracle/unfocused_callers.dot
+++ b/src/plugins/dive/tests/dive/oracle/unfocused_callers.dot
@@ -12,11 +12,11 @@ digraph G {
   
   subgraph cluster_cs_1 { label=<g>; cp2;
      };
-  subgraph cluster_cs_2 { label=<f3>; cp3;
+  subgraph cluster_cs_2 { label=<f1>; cp3;
      };
   subgraph cluster_cs_3 { label=<f2>; cp5;
      };
-  subgraph cluster_cs_4 { label=<f1>; cp7;
+  subgraph cluster_cs_4 { label=<f3>; cp7;
      };
   subgraph cluster_cs_5 { label=<main>; cp9;
      };
diff --git a/src/plugins/dive/tests/dive/oracle/various.dot b/src/plugins/dive/tests/dive/oracle/various.dot
index d661acee21a6b81d2dc2e4e1243d9adafee1eee7..0a9076386dcb14e7caaaf483c9ecafa96355fd46 100644
--- a/src/plugins/dive/tests/dive/oracle/various.dot
+++ b/src/plugins/dive/tests/dive/oracle/various.dot
@@ -1,69 +1,71 @@
 digraph G {
   cp2 [label=<x2>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
        style="filled,bold", ];
-  cp3 [label=<x>, shape=box, fillcolor="#AACCFF", color="#88AAFF",
+  cp3 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
        style="filled", ];
-  cp5 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
+  cp5 [label=<x>, shape=box, fillcolor="#AACCFF", color="#88AAFF",
        style="filled", ];
-  cp8 [label=<g>, shape=box, fillcolor="#AACCFF", color="#88AAFF",
+  cp9 [label=<g>, shape=box, fillcolor="#AACCFF", color="#88AAFF",
        style="filled", ];
-  cp11 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
+  cp11 [label=<0>, shape=ellipse, ];
+  cp13 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
         style="filled,bold", ];
-  cp12 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
+  cp14 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
         style="filled", ];
-  cp14 [label=<w>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
+  cp16 [label=<w>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
         style="filled", ];
-  cp16 [label=<x2>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
+  cp18 [label=<x2>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
         style="filled", ];
-  cp18 [label=<tmp_0>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
+  cp20 [label=<tmp_0>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
         style="filled", ];
-  cp21 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
+  cp22 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
         style="filled", ];
-  cp23 [label=<pf>, shape=box, fillcolor="#AACCFF", color="#88AAFF",
+  cp25 [label=<pf>, shape=box, fillcolor="#AACCFF", color="#88AAFF",
         style="filled", ];
-  cp25 [label=<x2>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
+  cp27 [label=<x2>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
         style="filled", ];
-  cp28 [label=<&amp; f>, shape=ellipse, ];
-  cp31 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
+  cp30 [label=<&amp; f>, shape=ellipse, ];
+  cp32 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000",
         style="filled", ];
-  cp34 [label=<is_nan_or_infinite: \is_finite((float)\mul_double((double)y, (double)2.0))>,
+  cp36 [label=<is_nan_or_infinite: \is_finite((float)\mul_double((double)y, (double)2.0))>,
         fillcolor="#FF0000", color="#FF0000", shape=doubleoctagon,
         style="filled,bold,bold", ];
-  cp36 [label=<is_nan_or_infinite: \is_finite(\add_float(y, w))>,
+  cp38 [label=<is_nan_or_infinite: \is_finite(\add_float(y, w))>,
         fillcolor="#FF0000", color="#FF0000", shape=doubleoctagon,
         style="filled,bold,bold", ];
   
-  subgraph cluster_cs_1 { label=<f>; cp34;cp5;cp2;
+  subgraph cluster_cs_1 { label=<f>; cp36;cp3;cp2;
      };
-  subgraph cluster_cs_2 { label=<main>; cp36;cp28;cp23;cp18;cp14;cp12;cp11;cp3;
-    subgraph cluster_cs_3 { label=<f>; cp21;cp16;
+  subgraph cluster_cs_2 { label=<main>; cp38;cp30;cp25;cp20;cp16;cp14;cp13;cp5;
+    subgraph cluster_cs_3 { label=<f>; cp22;cp18;
        };
-    subgraph cluster_cs_4 { label=<f>; cp31;cp25;
+    subgraph cluster_cs_4 { label=<f>; cp32;cp27;
        };
      };
-  subgraph cluster_file_1 { label=<various.i>; cp8;
+  subgraph cluster_file_1 { label=<various.i>; cp11;cp9;
      };
   
-  cp2 -> cp5;
+  cp2 -> cp3;
   cp3 -> cp2;
-  cp3 -> cp3;
-  cp3 -> cp16;
-  cp3 -> cp25;
+  cp3 -> cp36;
   cp5 -> cp2;
-  cp5 -> cp34;
-  cp8 -> cp3;
-  cp12 -> cp11;
-  cp12 -> cp36;
-  cp14 -> cp11;
-  cp14 -> cp36;
-  cp16 -> cp12;
-  cp16 -> cp21;
+  cp5 -> cp5;
+  cp5 -> cp18;
+  cp5 -> cp27;
+  cp9 -> cp5;
+  cp11 -> cp9;
+  cp14 -> cp13;
+  cp14 -> cp38;
+  cp16 -> cp13;
+  cp16 -> cp38;
   cp18 -> cp14;
-  cp21 -> cp16;
-  cp23 -> cp18 [color="#00FF00", ];
-  cp25 -> cp18;
-  cp25 -> cp31;
-  cp28 -> cp23;
-  cp31 -> cp25;
+  cp18 -> cp22;
+  cp20 -> cp16;
+  cp22 -> cp18;
+  cp25 -> cp20 [color="#00FF00", ];
+  cp27 -> cp20;
+  cp27 -> cp32;
+  cp30 -> cp25;
+  cp32 -> cp27;
   
   }
\ No newline at end of file
diff --git a/src/plugins/e-acsl/doc/Changelog b/src/plugins/e-acsl/doc/Changelog
index 4fb3fdb40ff2b7ba4d3a53fb6f57c3c264d80642..8d365c6d4a829724b44bdaac91bb6c491d01fb05 100644
--- a/src/plugins/e-acsl/doc/Changelog
+++ b/src/plugins/e-acsl/doc/Changelog
@@ -21,20 +21,24 @@
 #   configure   configure
 ###############################################################################
 
-############################
+###############################################################################
 Plugin E-ACSL <next-release>
-############################
+###############################################################################
+
+###############################################################################
+Plugin E-ACSL 27.0 (Cobalt)
+###############################################################################
 
 -! e-acsl-gcc   [2023-02-08] arguments to options -e/--cpp-flags now overload
 	        the default values set by e-acsl-gcc instead of being ignored.
 
-#########################
+###############################################################################
 Plugin E-ACSL 26.1 (Iron)
-#########################
+###############################################################################
 
-#########################
+###############################################################################
 Plugin E-ACSL 26.0 (Iron)
-#########################
+###############################################################################
 
 -* E-ACSL       [2022-11-08] Fix clashing name when a function with contract
 	        and a logic function have the same name (frama-c/eacsl#204).
@@ -48,9 +52,9 @@ Plugin E-ACSL 26.0 (Iron)
 -* E-ACSL       [2022-17-06] Fix wrong cast from pointer to integer
 	        (frama-c/frama-c#1119).
 
-##############################
+###############################################################################
 Plugin E-ACSL 25.0 (Manganese)
-##############################
+###############################################################################
 
 -* E-ACSL       [2022-23-05] Fix crash for quantifications over enum types
 	        (frama-c/e-acsl#199).
@@ -79,9 +83,9 @@ Plugin E-ACSL 25.0 (Manganese)
 -* E-ACSL       [2021-11-03] Now the same Frama-C options are used when parsing
                 the user sources and the E-ACSL's RTL.
 
-#############################
+###############################################################################
 Plugin E-ACSL 24.0 (Chromium)
-#############################
+###############################################################################
 
 -* E-ACSL       [2021-11-24] Fix code generation of properties proven invalid
                 with a previous analysis (frama-c/e-acsl#166).
@@ -116,9 +120,9 @@ Plugin E-ACSL 24.0 (Chromium)
                 range indices (frama-c/e-acsl#148).
 -* E-ACSL       [2021-06-04] Do not translate contracts of E-ACSL built-ins.
 
-#############################
+###############################################################################
 Plugin E-ACSL 23.1 (Vanadium)
-#############################
+###############################################################################
 
 -* E-ACSL       [2021-07-19] Fix crash occurring when two or more successive
                 logic coercions were done in a term (frama-c/e-acsl#172).
@@ -129,9 +133,9 @@ Plugin E-ACSL 23.1 (Vanadium)
 -* E-ACSL       [2021-07-13] Fix crash when encountering a GMP value in a loop
                 variant (frama-c/e-acsl#169).
 
-#############################
+###############################################################################
 Plugin E-ACSL 23.0 (Vanadium)
-#############################
+###############################################################################
 
 -* E-ACSL       [2021-05-25] Restore behavior of option -e-acsl-no-valid broken
                 since Titanium (included).
@@ -169,9 +173,9 @@ Plugin E-ACSL 23.0 (Vanadium)
 -  E-ACSL       [2020-11-17] Update e-acsl-gcc.sh so that the library dlmalloc
                 can be compiled and used from sources.
 
-#############################
+###############################################################################
 Plugin E-ACSL 22.0 (Titanium)
-#############################
+###############################################################################
 
 -* E-ACSL       [2020-11-16] Fix soundness bug when checking
                 initialization of a chunk of heap memory block.
@@ -208,9 +212,9 @@ Plugin E-ACSL 22.0 (Titanium)
 -* E-ACSL       [2020-06-18] Fix support of VLA memory tracking
                 (frama-c/e-acsl#119).
 
-#############################
+###############################################################################
 Plugin E-ACSL 21.0 (Scandium)
-#############################
+###############################################################################
 
 -* E-ACSL       [2020-06-10] Fix ##13: bug when mixing integers and floats in
                 annotations while -e-acsl-gmp-only is activated.
@@ -232,18 +236,18 @@ Plugin E-ACSL 21.0 (Scandium)
                 arrays that may lead to incorrect generated code.
 -* E-ACSL       [2019-12-04] Fix bug with compiler built-ins.
 
-############################
+###############################################################################
 Plugin E-ACSL 20.0 (Calcium)
-############################
+###############################################################################
 
 -  E-ACSL       [2019-08-28] Support of rational numbers and operations.
 -! E-ACSL       [2019-08-28] Deactivate the unsound support of real
                 numbers (that are not rationals). They were previously
                 unsoundly converted to floating point numbers.
 
-##############################
+###############################################################################
 Plugin E-ACSL 19.0 (Potassium)
-##############################
+###############################################################################
 
 -  E-ACSL       [2019-04-29] Support for logic functions and predicates
                 without labels.
@@ -263,9 +267,9 @@ Plugin E-ACSL 19.0 (Potassium)
 -  E-ACSL       [2018-11-15] Predicates with empty quantifications
                 directly generate \true or \false instead of nested loops.
 
-##########################
+###############################################################################
 Plugin E-ACSL 18.0 (Argon)
-##########################
+###############################################################################
 
 -* E-ACSL       [2018-11-13] Fix typing bug in quantifications when the
                 guards of the quantifier variable cannot be represented into
@@ -283,9 +287,9 @@ Plugin E-ACSL 18.0 (Argon)
 -  E-ACSL       [2018-09-18] Support for ranges in memory builtins
                 (\valid, \initialized, etc).
 
-######################################
+###############################################################################
 Plugin E-ACSL 17.0 (Chlorine-20180501)
-######################################
+###############################################################################
 
 -  E-ACSL       [2018-03-30] Support for let binding.
 -  E-ACSL       [2018-02-21] New option -e-acsl-replace-libc-functions to
@@ -312,9 +316,9 @@ Plugin E-ACSL 17.0 (Chlorine-20180501)
 -* E-ACSL       [2017-11-27] Restore behavior of option -e-acsl-valid broken
                 since Phosphorus (included).
 
-####################################
+###############################################################################
 Plugin E-ACSL 16.0 (Sulfur-20171101)
-####################################
+###############################################################################
 
 -* E-ACSL       [2017-10-25] Fix bug #2303 about unnamed formals in
                 annotated functions.
@@ -331,9 +335,9 @@ Plugin E-ACSL 16.0 (Sulfur-20171101)
                 e-acsl-gcc.sh allowing to change the default sizes of the
                 respective shadow spaces.
 
-########################################
+###############################################################################
 Plugin E-ACSL 15.0 (Phosphorus-20170501)
-########################################
+###############################################################################
 
 -  runtime      [2017-03-29] The (much more efficient) shadow memory model is
                 now used by default.
@@ -359,9 +363,9 @@ Plugin E-ACSL 15.0 (Phosphorus-20170501)
                 operations in a few cases: the generated code might have
                 overflowed.
 
-####################################
+###############################################################################
 Plugin E-ACSL 0.8 (Silicon-20161101)
-####################################
+###############################################################################
 
 -* e-acsl-gcc   [2016-11-07] Added --rte-select feature to e-acsl-gcc.sh.
 -* e-acsl-gcc   [2016-08-02] Added --rt-debug feature to e-acsl-gcc.sh.
@@ -397,9 +401,9 @@ Plugin E-ACSL 0.8 (Silicon-20161101)
                 initialization of tracked memory blocks in the E-ACSL
                 memory model library.
 
-######################################
+###############################################################################
 Plugin E-ACSL 0.6 (Magnesium_20151002)
-######################################
+###############################################################################
 
 -* e-acsl-gcc   [2016-01-22] Add an e-acsl-gcc.sh option allowing to skip
                 compilation of original sources.
@@ -413,9 +417,9 @@ Plugin E-ACSL 0.6 (Magnesium_20151002)
 -* runtime      [2015-11-06] Fix a crash occuring when using a recent libc
                 while GMP headers provided by E-ACSL are used.
 
-###################################
+###############################################################################
 Plugin E-ACSL 0.5 (Sodium_20150201)
-###################################
+###############################################################################
 
 -  E-ACSL       [2015-06-01] Support of \freeable. Thus illegal calls to
                 free (e.g. double free) are detected.
@@ -431,9 +435,9 @@ o  E-ACSL       [2014-12-17] Export a minimal API for other plug-ins.
 -* E-ACSL       [2014-10-27] Add a missing cast when translating an integral
                 type used in a floating point/real context in an annotation.
 
-###################################
+###############################################################################
 Plugin E-ACSL 0.4.1 (Neon_20140301)
-###################################
+###############################################################################
 
 -* E-ACSL       [2014-08-05] Fix bug #1838 about memset.
 -* E-ACSL       [2014-08-05] Fix bug #1818 about initialization of globals.
@@ -458,9 +462,9 @@ Plugin E-ACSL 0.4.1 (Neon_20140301)
                 generates incorrect code.
 -* E-ACSL       [2014-03-17] Fix bug #1700 about non-ISO empty struct.
 
-#################################
+###############################################################################
 Plugin E-ACSL 0.4 (Neon_20140301)
-#################################
+###############################################################################
 
 -* E-ACSL       [2014-01-28] Fix bug #1634 occuring in presence of static
                 addresses.
@@ -468,9 +472,9 @@ Plugin E-ACSL 0.4 (Neon_20140301)
                 of aliasing.
 -* E-ACSL       [2013-09-25] Some loop invariants were tagged as "assertions".
 
-#####################################
+###############################################################################
 Plugin E-ACSL 0.3 (Fluorine_20130601)
-#####################################
+###############################################################################
 
 -  E-ACSL       [2013-09-18] More precise message for unsupported contract
                 clauses.
@@ -488,9 +492,9 @@ Plugin E-ACSL 0.3 (Fluorine_20130601)
                 generated project.
 -* E-ACSL       [2013-05-30] Fix -e-acsl-debug n, with n >= 2.
 
-#####################################
+###############################################################################
 Plugin E-ACSL 0.2 (Fluorine_20130401)
-#####################################
+###############################################################################
 
 -  E-ACSL       [2013-01-09] New option -e-acsl-valid. By default, valid
                 annotation are not translated anymore.
@@ -527,10 +531,10 @@ Plugin E-ACSL 0.2 (Fluorine_20130401)
 -  E-ACSL       [2012-01-20] Use GMP arithmetics only when required
                 (i.e. mostly never in practice).
 
-#####################################
+###############################################################################
 Plugin E-ACSL 0.1 (Nitrogen_20111001)
-#####################################
+###############################################################################
 
 -  E-ACSL       [2012-01-06] First public release.
 
-###################################
+###############################################################################
diff --git a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcat.c b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcat.c
index 75bafb53733678a481528b1b45fc83a1dbf9a974..05ad2ab4d9630b9fc40e315b154e7f330e769fae 100644
--- a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcat.c
+++ b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcat.c
@@ -648,7 +648,7 @@ pid_t __gen_e_acsl_fork(void)
     __gen_e_acsl_assert_data.pred_txt = "\\result == 0 || \\result > 0 || \\result == -1";
     __gen_e_acsl_assert_data.file = "FRAMAC_SHARE/libc/unistd.h";
     __gen_e_acsl_assert_data.fct = "fork";
-    __gen_e_acsl_assert_data.line = 846;
+    __gen_e_acsl_assert_data.line = 853;
     __gen_e_acsl_assert_data.name = "result_ok_child_or_error";
     __e_acsl_assert(__gen_e_acsl_or_2,& __gen_e_acsl_assert_data);
     __e_acsl_assert_clean(& __gen_e_acsl_assert_data);
diff --git a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcmp.c b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcmp.c
index fa8adbe47e652c0494feefb8b30464727abafc11..b8a1cf816d1ff12b4a9d05f038ce82a244df2b9e 100644
--- a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcmp.c
+++ b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcmp.c
@@ -213,7 +213,7 @@ pid_t __gen_e_acsl_fork(void)
     __gen_e_acsl_assert_data.pred_txt = "\\result == 0 || \\result > 0 || \\result == -1";
     __gen_e_acsl_assert_data.file = "FRAMAC_SHARE/libc/unistd.h";
     __gen_e_acsl_assert_data.fct = "fork";
-    __gen_e_acsl_assert_data.line = 846;
+    __gen_e_acsl_assert_data.line = 853;
     __gen_e_acsl_assert_data.name = "result_ok_child_or_error";
     __e_acsl_assert(__gen_e_acsl_or_2,& __gen_e_acsl_assert_data);
     __e_acsl_assert_clean(& __gen_e_acsl_assert_data);
diff --git a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcpy.c b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcpy.c
index 4269e70a49c9e9183678c6bea3bfc8c98ce6cd4d..a82b19ca899af10ef56efa8cd421b733dc5a0352 100644
--- a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcpy.c
+++ b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcpy.c
@@ -627,7 +627,7 @@ pid_t __gen_e_acsl_fork(void)
     __gen_e_acsl_assert_data.pred_txt = "\\result == 0 || \\result > 0 || \\result == -1";
     __gen_e_acsl_assert_data.file = "FRAMAC_SHARE/libc/unistd.h";
     __gen_e_acsl_assert_data.fct = "fork";
-    __gen_e_acsl_assert_data.line = 846;
+    __gen_e_acsl_assert_data.line = 853;
     __gen_e_acsl_assert_data.name = "result_ok_child_or_error";
     __e_acsl_assert(__gen_e_acsl_or_2,& __gen_e_acsl_assert_data);
     __e_acsl_assert_clean(& __gen_e_acsl_assert_data);
diff --git a/src/plugins/e-acsl/tests/builtin/oracle/gen_strlen.c b/src/plugins/e-acsl/tests/builtin/oracle/gen_strlen.c
index b78f217fe8da244eedb82d0922e1e356a3d8086a..2fc62ec2c840513dda53a243873a8c22eccbcdcb 100644
--- a/src/plugins/e-acsl/tests/builtin/oracle/gen_strlen.c
+++ b/src/plugins/e-acsl/tests/builtin/oracle/gen_strlen.c
@@ -187,7 +187,7 @@ pid_t __gen_e_acsl_fork(void)
     __gen_e_acsl_assert_data.pred_txt = "\\result == 0 || \\result > 0 || \\result == -1";
     __gen_e_acsl_assert_data.file = "FRAMAC_SHARE/libc/unistd.h";
     __gen_e_acsl_assert_data.fct = "fork";
-    __gen_e_acsl_assert_data.line = 846;
+    __gen_e_acsl_assert_data.line = 853;
     __gen_e_acsl_assert_data.name = "result_ok_child_or_error";
     __e_acsl_assert(__gen_e_acsl_or_2,& __gen_e_acsl_assert_data);
     __e_acsl_assert_clean(& __gen_e_acsl_assert_data);
diff --git a/src/plugins/e-acsl/tests/builtin/oracle/strcat.res.oracle b/src/plugins/e-acsl/tests/builtin/oracle/strcat.res.oracle
index 79b6833073302250ad8fe4a1057ac2df85d67e12..3d4daab9ad5c01bd59d126de081bce4a0d624ff8 100644
--- a/src/plugins/e-acsl/tests/builtin/oracle/strcat.res.oracle
+++ b/src/plugins/e-acsl/tests/builtin/oracle/strcat.res.oracle
@@ -8,7 +8,7 @@
 [e-acsl] Warning: annotating undefined function `fork':
   the generated program may miss memory instrumentation
   if there are memory-related annotations.
-[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: 
+[e-acsl] FRAMAC_SHARE/libc/unistd.h:850: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:82: Warning: 
@@ -25,9 +25,9 @@
   is not yet supported.
   Ignoring annotation.
 [e-acsl] translation done in project "e-acsl".
-[eva:alarm] FRAMAC_SHARE/libc/unistd.h:846: Warning: 
+[eva:alarm] FRAMAC_SHARE/libc/unistd.h:853: Warning: 
   function __e_acsl_assert_register_int: precondition data->values == \null ||
                                                       \valid(data->values) got status unknown.
-[eva:alarm] FRAMAC_SHARE/libc/unistd.h:847: Warning: 
+[eva:alarm] FRAMAC_SHARE/libc/unistd.h:854: Warning: 
   function __e_acsl_assert_register_int: precondition data->values == \null ||
                                                       \valid(data->values) got status unknown.
diff --git a/src/plugins/e-acsl/tests/builtin/oracle/strcmp.res.oracle b/src/plugins/e-acsl/tests/builtin/oracle/strcmp.res.oracle
index 23aaebecb39a3031654d59684ee79c701659ffab..f0f2dd6bac7d240b1951d30131abcc48f249fc1b 100644
--- a/src/plugins/e-acsl/tests/builtin/oracle/strcmp.res.oracle
+++ b/src/plugins/e-acsl/tests/builtin/oracle/strcmp.res.oracle
@@ -49,7 +49,7 @@
 [e-acsl] FRAMAC_SHARE/libc/__fc_string_axiomatic.h:278: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
-[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: 
+[e-acsl] FRAMAC_SHARE/libc/unistd.h:850: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:82: Warning: 
diff --git a/src/plugins/e-acsl/tests/builtin/oracle/strcpy.res.oracle b/src/plugins/e-acsl/tests/builtin/oracle/strcpy.res.oracle
index 4d60df21bef6e71b55d35f9d70e3f0a80081b3b3..ef798a2e8602f3a65f86a373bfa895fbab1a7e81 100644
--- a/src/plugins/e-acsl/tests/builtin/oracle/strcpy.res.oracle
+++ b/src/plugins/e-acsl/tests/builtin/oracle/strcpy.res.oracle
@@ -44,7 +44,7 @@
 [e-acsl] FRAMAC_SHARE/libc/__fc_string_axiomatic.h:278: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
-[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: 
+[e-acsl] FRAMAC_SHARE/libc/unistd.h:850: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:82: Warning: 
diff --git a/src/plugins/e-acsl/tests/builtin/oracle/strlen.res.oracle b/src/plugins/e-acsl/tests/builtin/oracle/strlen.res.oracle
index 08078ac2fc031bffaaa0258a46f0b6d74806cc7f..1d60323480135dccc0464552181b36d335b2ba1f 100644
--- a/src/plugins/e-acsl/tests/builtin/oracle/strlen.res.oracle
+++ b/src/plugins/e-acsl/tests/builtin/oracle/strlen.res.oracle
@@ -47,7 +47,7 @@
 [e-acsl] FRAMAC_SHARE/libc/__fc_string_axiomatic.h:278: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
-[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: 
+[e-acsl] FRAMAC_SHARE/libc/unistd.h:850: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:82: Warning: 
diff --git a/src/plugins/e-acsl/tests/concurrency/oracle/gen_parallel_threads.c b/src/plugins/e-acsl/tests/concurrency/oracle/gen_parallel_threads.c
index ab5af04d3e66f2fa394eb2e386923b28d33192b0..fae60f07a4bcf944b858ecc1f37eab71b82be061 100644
--- a/src/plugins/e-acsl/tests/concurrency/oracle/gen_parallel_threads.c
+++ b/src/plugins/e-acsl/tests/concurrency/oracle/gen_parallel_threads.c
@@ -750,7 +750,7 @@ int __gen_e_acsl_usleep(useconds_t usec)
     __gen_e_acsl_assert_data.pred_txt = "\\result == 0 || \\result == -1";
     __gen_e_acsl_assert_data.file = "FRAMAC_SHARE/libc/unistd.h";
     __gen_e_acsl_assert_data.fct = "usleep";
-    __gen_e_acsl_assert_data.line = 1145;
+    __gen_e_acsl_assert_data.line = 1152;
     __gen_e_acsl_assert_data.name = "result_ok_or_error";
     __e_acsl_assert(__gen_e_acsl_or,& __gen_e_acsl_assert_data);
     __e_acsl_assert_clean(& __gen_e_acsl_assert_data);
@@ -1717,7 +1717,7 @@ void __e_acsl_globals_init(void)
     __e_acsl_full_init((void *)(& perror));
     __e_acsl_store_block((void *)(& __fc_p_tmpnam),8UL);
     __e_acsl_full_init((void *)(& __fc_p_tmpnam));
-    __e_acsl_store_block((void *)(__fc_tmpnam),2048UL);
+    __e_acsl_store_block((void *)(__fc_tmpnam),20UL);
     __e_acsl_full_init((void *)(& __fc_tmpnam));
     __e_acsl_store_block((void *)(& __fc_p_fopen),8UL);
     __e_acsl_full_init((void *)(& __fc_p_fopen));
diff --git a/src/plugins/e-acsl/tests/concurrency/oracle/gen_threads_debug.c b/src/plugins/e-acsl/tests/concurrency/oracle/gen_threads_debug.c
index 77907fea3c8271b68ac82049c7141bb1bdc41627..c1b193f256bdb4dfd424e2e088cc6a97a9929acf 100644
--- a/src/plugins/e-acsl/tests/concurrency/oracle/gen_threads_debug.c
+++ b/src/plugins/e-acsl/tests/concurrency/oracle/gen_threads_debug.c
@@ -432,7 +432,7 @@ int __gen_e_acsl_usleep(useconds_t usec)
     __gen_e_acsl_assert_data.pred_txt = "\\result == 0 || \\result == -1";
     __gen_e_acsl_assert_data.file = "FRAMAC_SHARE/libc/unistd.h";
     __gen_e_acsl_assert_data.fct = "usleep";
-    __gen_e_acsl_assert_data.line = 1145;
+    __gen_e_acsl_assert_data.line = 1152;
     __gen_e_acsl_assert_data.name = "result_ok_or_error";
     __e_acsl_assert(__gen_e_acsl_or,& __gen_e_acsl_assert_data);
     __e_acsl_assert_clean(& __gen_e_acsl_assert_data);
@@ -1399,7 +1399,7 @@ void __e_acsl_globals_init(void)
     __e_acsl_full_init((void *)(& perror));
     __e_acsl_store_block((void *)(& __fc_p_tmpnam),8UL);
     __e_acsl_full_init((void *)(& __fc_p_tmpnam));
-    __e_acsl_store_block((void *)(__fc_tmpnam),2048UL);
+    __e_acsl_store_block((void *)(__fc_tmpnam),20UL);
     __e_acsl_full_init((void *)(& __fc_tmpnam));
     __e_acsl_store_block((void *)(& __fc_p_fopen),8UL);
     __e_acsl_full_init((void *)(& __fc_p_fopen));
diff --git a/src/plugins/e-acsl/tests/concurrency/oracle/gen_threads_safe_locations.c b/src/plugins/e-acsl/tests/concurrency/oracle/gen_threads_safe_locations.c
index 5228bebf9ee603886848d3b89dbabe3cd84cc4f5..3113cefa8b2f90ffb5b527648584b9295619fe39 100644
--- a/src/plugins/e-acsl/tests/concurrency/oracle/gen_threads_safe_locations.c
+++ b/src/plugins/e-acsl/tests/concurrency/oracle/gen_threads_safe_locations.c
@@ -492,7 +492,7 @@ void __e_acsl_globals_init(void)
     __e_acsl_full_init((void *)(& thread_start));
     __e_acsl_store_block((void *)(& __fc_p_tmpnam),8UL);
     __e_acsl_full_init((void *)(& __fc_p_tmpnam));
-    __e_acsl_store_block((void *)(__fc_tmpnam),2048UL);
+    __e_acsl_store_block((void *)(__fc_tmpnam),20UL);
     __e_acsl_full_init((void *)(& __fc_tmpnam));
     __e_acsl_store_block((void *)(& __fc_p_fopen),8UL);
     __e_acsl_full_init((void *)(& __fc_p_fopen));
diff --git a/src/plugins/e-acsl/tests/concurrency/oracle/parallel_threads.res.oracle b/src/plugins/e-acsl/tests/concurrency/oracle/parallel_threads.res.oracle
index 2c771c66bd1bdcf46f73936f65aea84f732108ff..26bee74a6dea8e54ad16b3b067774451af038ea4 100644
--- a/src/plugins/e-acsl/tests/concurrency/oracle/parallel_threads.res.oracle
+++ b/src/plugins/e-acsl/tests/concurrency/oracle/parallel_threads.res.oracle
@@ -35,7 +35,7 @@
 [e-acsl] Warning: annotating undefined function `usleep':
   the generated program may miss memory instrumentation
   if there are memory-related annotations.
-[e-acsl] FRAMAC_SHARE/libc/unistd.h:1142: Warning: 
+[e-acsl] FRAMAC_SHARE/libc/unistd.h:1149: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/stdlib.h:505: Warning: 
@@ -169,6 +169,6 @@
 [eva:alarm] FRAMAC_SHARE/libc/pthread.h:316: Warning: 
   function __e_acsl_assert_register_int: precondition data->values == \null ||
                                                       \valid(data->values) got status unknown.
-[eva:alarm] FRAMAC_SHARE/libc/unistd.h:1145: Warning: 
+[eva:alarm] FRAMAC_SHARE/libc/unistd.h:1152: Warning: 
   function __e_acsl_assert_register_int: precondition data->values == \null ||
                                                       \valid(data->values) got status unknown.
diff --git a/src/plugins/e-acsl/tests/concurrency/oracle/threads_debug.res.oracle b/src/plugins/e-acsl/tests/concurrency/oracle/threads_debug.res.oracle
index 2c771c66bd1bdcf46f73936f65aea84f732108ff..26bee74a6dea8e54ad16b3b067774451af038ea4 100644
--- a/src/plugins/e-acsl/tests/concurrency/oracle/threads_debug.res.oracle
+++ b/src/plugins/e-acsl/tests/concurrency/oracle/threads_debug.res.oracle
@@ -35,7 +35,7 @@
 [e-acsl] Warning: annotating undefined function `usleep':
   the generated program may miss memory instrumentation
   if there are memory-related annotations.
-[e-acsl] FRAMAC_SHARE/libc/unistd.h:1142: Warning: 
+[e-acsl] FRAMAC_SHARE/libc/unistd.h:1149: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/stdlib.h:505: Warning: 
@@ -169,6 +169,6 @@
 [eva:alarm] FRAMAC_SHARE/libc/pthread.h:316: Warning: 
   function __e_acsl_assert_register_int: precondition data->values == \null ||
                                                       \valid(data->values) got status unknown.
-[eva:alarm] FRAMAC_SHARE/libc/unistd.h:1145: Warning: 
+[eva:alarm] FRAMAC_SHARE/libc/unistd.h:1152: Warning: 
   function __e_acsl_assert_register_int: precondition data->values == \null ||
                                                       \valid(data->values) got status unknown.
diff --git a/src/plugins/e-acsl/tests/constructs/oracle/gen_printed_data.c b/src/plugins/e-acsl/tests/constructs/oracle/gen_printed_data.c
index 4204fcd3ed9ba4bacc3a12bcddb6007ff628a85e..b189489a114c9c540fb33df1cc23919b2f7c0454 100644
--- a/src/plugins/e-acsl/tests/constructs/oracle/gen_printed_data.c
+++ b/src/plugins/e-acsl/tests/constructs/oracle/gen_printed_data.c
@@ -21,16 +21,16 @@ enum EBool {
     EBOOL_MAX = (_Bool)1
 };
 enum EChar {
-    ECHAR_MIN = (char)(-128),
+    ECHAR_MIN = (char)(-127 - 1),
     ECHAR_MAX = (char)127
 };
 enum ESChar {
-    ESCHAR_MIN = (signed char)(-128),
+    ESCHAR_MIN = (signed char)(-127 - 1),
     ESCHAR_MAX = (signed char)127
 };
 enum EUChar {
     EUCHAR_MIN = (unsigned char)0,
-    EUCHAR_MAX = (unsigned char)255
+    EUCHAR_MAX = (unsigned char)255U
 };
 enum EInt {
     EINT_MIN = -2147483647 - 1,
@@ -41,12 +41,12 @@ enum EUInt {
     EUINT_MAX = 4294967295U
 };
 enum EShort {
-    ESHORT_MIN = (short)(-32768),
+    ESHORT_MIN = (short)(-32767 - 1),
     ESHORT_MAX = (short)32767
 };
 enum EUShort {
     EUSHORT_MIN = (unsigned short)0,
-    EUSHORT_MAX = (unsigned short)65535
+    EUSHORT_MAX = (unsigned short)65535U
 };
 enum ELong {
     ELONG_MIN = -9223372036854775807L - 1L,
@@ -164,7 +164,7 @@ int main(void)
     __e_acsl_assert_clean(& __gen_e_acsl_assert_data_3);
   }
   /*@ assert \let x = int_schar; \true; */ ;
-  unsigned char int_uchar = (unsigned char)255;
+  unsigned char int_uchar = (unsigned char)255U;
   __e_acsl_store_block((void *)(& int_uchar),1UL);
   __e_acsl_full_init((void *)(& int_uchar));
   {
@@ -244,7 +244,7 @@ int main(void)
     __e_acsl_assert_clean(& __gen_e_acsl_assert_data_7);
   }
   /*@ assert \let x = int_short; \true; */ ;
-  unsigned short int_ushort = (unsigned short)65535;
+  unsigned short int_ushort = (unsigned short)65535U;
   __e_acsl_store_block((void *)(& int_ushort),2UL);
   __e_acsl_full_init((void *)(& int_ushort));
   {
@@ -423,8 +423,7 @@ int main(void)
   }
   /*@ assert \let x = real_double; \true; */ ;
   /*@ assert
-      Eva: is_nan_or_infinite:
-        \is_finite((long double)0x1.fffffffffffffffep+16383L);
+      Eva: is_nan_or_infinite: \is_finite(0x1.fffffffffffffffep+16383L);
   */
   long double real_ldouble = 0x1.fffffffffffffffep+16383L;
   __e_acsl_store_block((void *)(& real_ldouble),16UL);
diff --git a/src/plugins/e-acsl/tests/constructs/oracle/printed_data.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle/printed_data.res.oracle
index 2bc5c16105b06b1f77eafeb26a46b63d4e260432..f9589246d101d590ef5796c6a6b6ca0e6620532d 100644
--- a/src/plugins/e-acsl/tests/constructs/oracle/printed_data.res.oracle
+++ b/src/plugins/e-acsl/tests/constructs/oracle/printed_data.res.oracle
@@ -21,7 +21,7 @@
   cannot parse floating-point constant, returning imprecise result
 [eva:alarm] printed_data.c:101: Warning: 
   non-finite long double value.
-  assert \is_finite((long double)0x1.fffffffffffffffep+16383L);
+  assert \is_finite(0x1.fffffffffffffffep+16383L);
 [eva:alarm] printed_data.c:102: Warning: 
   non-finite long double value. assert \is_finite(real_ldouble);
 [eva:alarm] printed_data.c:102: Warning: 
diff --git a/src/plugins/e-acsl/tests/format/oracle/fprintf.res.oracle b/src/plugins/e-acsl/tests/format/oracle/fprintf.res.oracle
index 658935448b79860faf628778090446a16a2f2b6e..618817f8cf34a55412723b544aee62e28e882b65 100644
--- a/src/plugins/e-acsl/tests/format/oracle/fprintf.res.oracle
+++ b/src/plugins/e-acsl/tests/format/oracle/fprintf.res.oracle
@@ -14,7 +14,7 @@
 [e-acsl] Warning: annotating undefined function `fork':
   the generated program may miss memory instrumentation
   if there are memory-related annotations.
-[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: 
+[e-acsl] FRAMAC_SHARE/libc/unistd.h:850: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:82: Warning: 
@@ -42,10 +42,10 @@
   is not yet supported.
   Ignoring annotation.
 [e-acsl] translation done in project "e-acsl".
-[eva:alarm] FRAMAC_SHARE/libc/unistd.h:846: Warning: 
+[eva:alarm] FRAMAC_SHARE/libc/unistd.h:853: Warning: 
   function __e_acsl_assert_register_int: precondition data->values == \null ||
                                                       \valid(data->values) got status unknown.
-[eva:alarm] FRAMAC_SHARE/libc/unistd.h:847: Warning: 
+[eva:alarm] FRAMAC_SHARE/libc/unistd.h:854: Warning: 
   function __e_acsl_assert_register_int: precondition data->values == \null ||
                                                       \valid(data->values) got status unknown.
 [kernel:annot:missing-spec] fprintf.c:22: Warning: 
diff --git a/src/plugins/e-acsl/tests/format/oracle/gen_fprintf.c b/src/plugins/e-acsl/tests/format/oracle/gen_fprintf.c
index 437ed75a82541931cfc0f3a34996233d94d3bdf3..bb0d77edd343e52a469b3adcad7fc8a484a33197 100644
--- a/src/plugins/e-acsl/tests/format/oracle/gen_fprintf.c
+++ b/src/plugins/e-acsl/tests/format/oracle/gen_fprintf.c
@@ -126,7 +126,7 @@ pid_t __gen_e_acsl_fork(void)
     __gen_e_acsl_assert_data.pred_txt = "\\result == 0 || \\result > 0 || \\result == -1";
     __gen_e_acsl_assert_data.file = "FRAMAC_SHARE/libc/unistd.h";
     __gen_e_acsl_assert_data.fct = "fork";
-    __gen_e_acsl_assert_data.line = 846;
+    __gen_e_acsl_assert_data.line = 853;
     __gen_e_acsl_assert_data.name = "result_ok_child_or_error";
     __e_acsl_assert(__gen_e_acsl_or_2,& __gen_e_acsl_assert_data);
     __e_acsl_assert_clean(& __gen_e_acsl_assert_data);
diff --git a/src/plugins/e-acsl/tests/format/oracle/gen_printf.c b/src/plugins/e-acsl/tests/format/oracle/gen_printf.c
index 7526a0f39b5452827752d424283bb425a0e4179c..0dd82c4b10993096f678d8ba7c2d3fe5fee2e9d0 100644
--- a/src/plugins/e-acsl/tests/format/oracle/gen_printf.c
+++ b/src/plugins/e-acsl/tests/format/oracle/gen_printf.c
@@ -1019,7 +1019,7 @@ pid_t __gen_e_acsl_fork(void)
     __gen_e_acsl_assert_data.pred_txt = "\\result == 0 || \\result > 0 || \\result == -1";
     __gen_e_acsl_assert_data.file = "FRAMAC_SHARE/libc/unistd.h";
     __gen_e_acsl_assert_data.fct = "fork";
-    __gen_e_acsl_assert_data.line = 846;
+    __gen_e_acsl_assert_data.line = 853;
     __gen_e_acsl_assert_data.name = "result_ok_child_or_error";
     __e_acsl_assert(__gen_e_acsl_or_2,& __gen_e_acsl_assert_data);
     __e_acsl_assert_clean(& __gen_e_acsl_assert_data);
diff --git a/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle b/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle
index 1eaec8a8f39741aa8937f21524340247e6280696..02fda025503b0601a9443c74d7d377448cb04c66 100644
--- a/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle
+++ b/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle
@@ -81,7 +81,7 @@
   E-ACSL construct `logic functions or predicates performing read accesses'
   is not yet supported.
   Ignoring annotation.
-[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: 
+[e-acsl] FRAMAC_SHARE/libc/unistd.h:850: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:82: Warning: 
@@ -105,10 +105,10 @@
   is not yet supported.
   Ignoring annotation.
 [e-acsl] translation done in project "e-acsl".
-[eva:alarm] FRAMAC_SHARE/libc/unistd.h:846: Warning: 
+[eva:alarm] FRAMAC_SHARE/libc/unistd.h:853: Warning: 
   function __e_acsl_assert_register_int: precondition data->values == \null ||
                                                       \valid(data->values) got status unknown.
-[eva:alarm] FRAMAC_SHARE/libc/unistd.h:847: Warning: 
+[eva:alarm] FRAMAC_SHARE/libc/unistd.h:854: Warning: 
   function __e_acsl_assert_register_int: precondition data->values == \null ||
                                                       \valid(data->values) got status unknown.
 [kernel:annot:missing-spec] printf.c:190: Warning: 
diff --git a/src/plugins/e-acsl/tests/temporal/oracle/gen_t_fun_lib.c b/src/plugins/e-acsl/tests/temporal/oracle/gen_t_fun_lib.c
index 8810b1add07155c58bb699ce351a65cbd6c8928c..354f67ce51f263016bbd315a37cb77ec93aab093 100644
--- a/src/plugins/e-acsl/tests/temporal/oracle/gen_t_fun_lib.c
+++ b/src/plugins/e-acsl/tests/temporal/oracle/gen_t_fun_lib.c
@@ -31,7 +31,7 @@ int main(void)
   char *c = (char *)__gen_e_acsl_literal_string;
   __e_acsl_temporal_reset_parameters();
   __e_acsl_temporal_reset_return();
-  char *p = malloc((size_t)256);
+  char *p = malloc((size_t)4096);
   __e_acsl_temporal_store_nblock((void *)(& p),(void *)*(& p));
   __e_acsl_store_block((void *)(& p),8UL);
   __e_acsl_full_init((void *)(& p));
@@ -42,7 +42,7 @@ int main(void)
   __e_acsl_full_init((void *)(& q));
   __e_acsl_temporal_reset_parameters();
   __e_acsl_temporal_reset_return();
-  q = (char *)malloc((size_t)256);
+  q = (char *)malloc((size_t)4096);
   __e_acsl_temporal_store_nblock((void *)(& q),(void *)*(& q));
   {
     int __gen_e_acsl_initialized;
diff --git a/src/plugins/e-acsl/tests/test_config_dev b/src/plugins/e-acsl/tests/test_config_dev
index e98e5eb62f93de601cb5e0f75f480a7b5df64a4f..ee637413caa074f7a35b7f7d482396ca83d8158f 100644
--- a/src/plugins/e-acsl/tests/test_config_dev
+++ b/src/plugins/e-acsl/tests/test_config_dev
@@ -7,6 +7,9 @@ MACRO: ROOT_EACSL_GCC_MISC_OPTS -q -X --no-assert-print-data
 COMMENT: Default options for the frama-c invocation
 MACRO: ROOT_EACSL_GCC_FC_EXTRA -verbose 0
 
+COMMENT: Currently compilation assumes an x86_64 architecture
+ENABLED_IF: (= %{architecture} x86_64)
+
 PLUGIN: e-acsl eva,scope,variadic rtegen
 
 COMMENT: The dependency to the plugin share directory has not to be explicited
diff --git a/src/plugins/eva/api/general_requests.ml b/src/plugins/eva/api/general_requests.ml
index 3c75a9020251e3775500b6531321d49bcabcdb8f..d3085ad822cb528b62bcffc5a61cea4ea055f09c 100644
--- a/src/plugins/eva/api/general_requests.ml
+++ b/src/plugins/eva/api/general_requests.ml
@@ -39,7 +39,8 @@ module ComputationState = struct
       Package.(Junion [
           Jtag "not_computed" ;
           Jtag "computing" ;
-          Jtag "computed"])
+          Jtag "computed" ;
+          Jtag "aborted" ])
   let to_json = function
     | Analysis.NotComputed -> `String "not_computed"
     | Computing -> `String "computing"
@@ -47,7 +48,7 @@ module ComputationState = struct
     | Aborted -> `String "aborted"
 end
 
-let _computation_signal =
+let computation_signal =
   States.register_value ~package
     ~name:"computationState"
     ~descr:(Markdown.plain "The current computation state of the analysis.")
@@ -84,8 +85,31 @@ let () = Request.register ~package
     ~kind:`GET ~name:"getCallers"
     ~descr:(Markdown.plain "Get the list of call site of a function")
     ~input:(module Kernel_ast.Function) ~output:(module Data.Jlist (CallSite))
+    ~signals:[computation_signal]
     callers
 
+let eval_callee stmt lval =
+  let expr = Eva_utils.lval_to_exp lval in
+  Results.(before stmt |> eval_callee expr |> default [])
+
+let callees = function
+  | Printer_tag.PLval (_kf, Kstmt stmt, (Mem _, NoOffset as lval))
+    when Cil.(isFunctionType (typeOfLval lval)) ->
+    eval_callee stmt lval
+  | Printer_tag.PLval (_kf, Kstmt stmt, lval)
+    when Cil.(isFunPtrType (Cil.typeOfLval lval)) ->
+    eval_callee stmt (Mem (Eva_utils.lval_to_exp lval), NoOffset)
+  | _ -> []
+
+let () = Request.register ~package
+    ~kind:`GET ~name:"getCallees"
+    ~descr:(Markdown.plain
+              "Return the functions pointed to by a function pointer")
+    ~input:(module Kernel_ast.Marker)
+    ~output:(module Data.Jlist (Kernel_ast.Function))
+    ~signals:[computation_signal]
+    callees
+
 (* ----- Functions ---------------------------------------------------------- *)
 
 module Functions =
@@ -177,37 +201,95 @@ let () = Request.register ~package
                             statements in a function")
     ~input:(module Kernel_ast.Function)
     ~output:(module DeadCode)
+    ~signals:[computation_signal]
     dead_code
 
 
 
 (* ----- Register Eva values information ------------------------------------ *)
 
-let term_lval_to_lval tlval =
-  try Logic_to_c.term_lval_to_lval tlval
+type evaluation_point =
+  | Initial
+  | Pre of kernel_function
+  | Stmt of kernel_function * stmt
+
+let post kf =
+  if Analysis.use_spec_instead_of_definition kf
+  then raise Not_found
+  else
+    try Stmt (kf, Kernel_function.find_return kf)
+    with Kernel_function.No_Statement -> raise Not_found
+
+let request_at = function
+  | Initial -> Results.at_start
+  | Stmt (_, stmt) -> Results.before stmt
+  | Pre kf -> Results.at_start_of kf
+
+let property_evaluation_point = function
+  | Property.IPCodeAnnot { ica_kf = kf; ica_stmt = stmt }
+  | IPPropertyInstance { ii_kf = kf; ii_stmt = stmt } -> Stmt (kf, stmt)
+  | IPPredicate {ip_kf; ip_kind = PKEnsures (_, Normal)} -> post ip_kf
+  | IPPredicate { ip_kf = kf;
+                  ip_kind = PKRequires _ | PKAssumes _ | PKTerminates }
+  | IPAssigns {ias_kf = kf} | IPFrom {if_kf = kf} ->
+    Pre kf
+  | IPPredicate _ | IPComplete _ | IPDisjoint _ | IPDecrease _
+  | IPAxiomatic _ | IPLemma _ | IPTypeInvariant _ | IPGlobalInvariant _
+  | IPOther _ | IPAllocation _ | IPReachable _ | IPExtended _ | IPBehavior _ ->
+    raise Not_found
+
+let marker_evaluation_point = function
+  | Printer_tag.PGlobal _ -> Initial
+  | PStmt (kf, stmt) | PStmtStart (kf, stmt) -> Stmt (kf, stmt)
+  | PVDecl (kf, kinstr, v) when not (v.vformal || v.vglob) ->
+    begin
+      (* Only evaluate declaration of local variable if it is initialized. *)
+      match kf, kinstr with
+      | Some kf, Kstmt ({skind = Instr (Local_init _)} as s) -> Stmt (kf, s)
+      | _ -> raise Not_found
+    end
+  | PLval (kf, ki, _) | PExp (kf, ki, _) | PVDecl (kf, ki, _) ->
+    begin
+      match kf, ki with
+      | Some kf, Kstmt stmt -> Stmt (kf, stmt)
+      | Some kf, Kglobal -> Pre kf
+      | None, Kglobal -> Initial
+      | None, Kstmt _ -> assert false
+    end
+  | PTermLval (_, _, prop, _) | PIP prop -> property_evaluation_point prop
+  | PType _ -> raise Not_found
+
+let term_lval_to_lval kf tlval =
+  try
+    let result = Option.bind kf Eva_utils.find_return_var in
+    Logic_to_c.term_lval_to_lval ?result tlval
   with Logic_to_c.No_conversion -> raise Not_found
 
 let print_value fmt loc =
   let is_scalar = Cil.isScalarType in
-  let kinstr, eval =
+  let evaluation_point = marker_evaluation_point loc in
+  let request = request_at evaluation_point in
+  let eval =
     match loc with
-    | Printer_tag.PLval (_kf, ki, lval) when is_scalar (Cil.typeOfLval lval) ->
-      ki, Results.eval_lval lval
-    | Printer_tag.PExp (_kf, ki, expr) when is_scalar (Cil.typeOf expr) ->
-      ki, Results.eval_exp expr
-    | PVDecl (_kf, ki, vi) when is_scalar vi.vtype ->
-      ki, Results.eval_var vi
-    | PTermLval (_kf, ki, _ip, tlval) ->
-      let lval = term_lval_to_lval tlval in
-      ki, Results.eval_lval lval
+    | Printer_tag.PLval (_, _, lval) when is_scalar (Cil.typeOfLval lval) ->
+      Results.eval_lval lval
+    | Printer_tag.PExp (_, _, expr) when is_scalar (Cil.typeOf expr) ->
+      Results.eval_exp expr
+    | PVDecl (_, _, vi) when is_scalar vi.vtype ->
+      Results.eval_var vi
+    | PTermLval (kf, _, _ip, tlval) ->
+      let lval = term_lval_to_lval kf tlval in
+      if is_scalar (Cil.typeOfLval lval)
+      then Results.eval_lval lval
+      else raise Not_found
     | _ -> raise Not_found
   in
   let pretty = Cvalue.V_Or_Uninitialized.pretty in
   let eval_cvalue at = Results.(eval at |> as_cvalue_or_uninitialized) in
-  let before = eval_cvalue (Results.before_kinstr kinstr) in
-  match kinstr with
-  | Kglobal -> pretty fmt before
-  | Kstmt stmt ->
+  let before = eval_cvalue request in
+  match evaluation_point with
+  | Initial | Pre _ -> pretty fmt before
+  | Stmt (_, stmt) ->
     let after = eval_cvalue (Results.after stmt) in
     if Cvalue.V_Or_Uninitialized.equal before after
     then pretty fmt before
@@ -241,8 +323,8 @@ module EvaTaints = struct
       | PLval (_, Kstmt stmt, lval) -> Some (expr_of_lval lval, stmt)
       | PExp (_, Kstmt stmt, expr) -> Some (expr, stmt)
       | PVDecl (_, Kstmt stmt, vi) -> Some (expr_of_lval (Var vi, NoOffset), stmt)
-      | PTermLval (_, Kstmt stmt, _, tlval) ->
-        Some (term_lval_to_lval tlval |> expr_of_lval, stmt)
+      | PTermLval (kf, Kstmt stmt, _, tlval) ->
+        Some (term_lval_to_lval kf tlval |> expr_of_lval, stmt)
       | _ -> None
 
   let of_marker marker =
@@ -394,6 +476,7 @@ module LvalueTaints = struct
       ~descr:(Markdown.plain "Get the tainted lvalues of a given function")
       ~input:(module (Kernel_ast.Fundec))
       ~output:(module (Data.Jlist (Status)))
+      ~signals:[computation_signal]
       get_tainted_lvals
 end
 
@@ -749,4 +832,7 @@ let () = Request.register ~package
     ~input:(module Data.Jpair (Kernel_ast.Marker) (Data.Jbool))
     ~output:(module Data.Jlist
           (Data.Jtriple (Data.Jstring) (Data.Jstring) (Data.Jstring)))
+    ~signals:[computation_signal]
     get_states
+
+(* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/eva/api/general_requests.mli b/src/plugins/eva/api/general_requests.mli
index 6472763b7e5187d8703feffb06c7581d7b81282f..7e98550daa190962d7250a23df777bc81c9d9d7a 100644
--- a/src/plugins/eva/api/general_requests.mli
+++ b/src/plugins/eva/api/general_requests.mli
@@ -21,3 +21,18 @@
 (**************************************************************************)
 
 (** General Eva requests registered in the server. *)
+
+open Cil_types
+
+type evaluation_point =
+  | Initial
+  | Pre of kernel_function
+  | Stmt of kernel_function * stmt
+
+(* Returns the evaluation point of a marker.
+   @raise Not_found if the marker cannot be evaluated. *)
+val marker_evaluation_point: Printer_tag.localizable -> evaluation_point
+
+(* Converts an ACSL lval into a C lval.
+   @raise Not_found if the conversion fails. *)
+val term_lval_to_lval: kernel_function option -> term_lval -> lval
diff --git a/src/plugins/eva/api/values_request.ml b/src/plugins/eva/api/values_request.ml
index c672982553d0d692ed28822bfcb09146bd3d04bc..1e109a39629a2e95115db3b403be1112542972ba 100644
--- a/src/plugins/eva/api/values_request.ml
+++ b/src/plugins/eva/api/values_request.ml
@@ -42,9 +42,12 @@ let package =
     ~title:"Eva Values"
     ()
 
-type probe =
-  | Pexpr of exp * stmt
-  | Plval of lval * stmt
+type term = Pexpr of exp | Plval of lval | Ppred of predicate
+type evaluation_point = General_requests.evaluation_point =
+    Initial | Pre of kernel_function | Stmt of kernel_function * stmt
+
+(* A term and the program point where it should be evaluated. *)
+type probe = term * evaluation_point
 
 type callstack = Value_types.callstack
 type truth = Abstract_interp.truth
@@ -81,32 +84,53 @@ let () = Analysis.register_computation_hook ~on:Computed
 (* --- Marker Utilities                                                   --- *)
 (* -------------------------------------------------------------------------- *)
 
-let next_steps s =
-  match s.skind with
-  | If (cond, _, _, _) -> [ `Then cond ; `Else cond ]
-  | Instr (Set _ | Call _ | Local_init _) -> [ `After ]
-  | Instr (Asm _ | Code_annot _)
-  | Switch _ | Loop _ | Block _ | UnspecifiedSequence _
-  | TryCatch _ | TryFinally _ | TryExcept _
-  | Instr (Skip _) | Return _ | Break _ | Continue _ | Goto _ | Throw _ -> []
-
-let probe_stmt s =
-  match s.skind with
-  | Instr (Set(lv,_,_)) -> Some (Plval (lv,s))
-  | Instr (Call(Some lr,_,_,_)) -> Some (Plval (lr,s))
-  | Instr (Local_init(v,_,_)) -> Some (Plval ((Var v,NoOffset), s))
-  | Return (Some e,_) | If(e,_,_,_) | Switch(e,_,_,_) -> Some (Pexpr (e,s))
-  | _ -> None
+let next_steps = function
+  | Initial | Pre _ -> []
+  | Stmt (_, stmt) ->
+    match stmt.skind with
+    | If (cond, _, _, _) -> [ `Then cond ; `Else cond ]
+    | Instr (Set _ | Call _ | Local_init _) -> [ `After ]
+    | Instr (Asm _ | Code_annot _)
+    | Switch _ | Loop _ | Block _ | UnspecifiedSequence _
+    | TryCatch _ | TryFinally _ | TryExcept _
+    | Instr (Skip _) | Return _ | Break _ | Continue _ | Goto _ | Throw _ -> []
+
+let probe_stmt stmt =
+  match stmt.skind with
+  | Instr (Set (lv, _, _))
+  | Instr (Call (Some lv, _, _, _)) -> Plval lv
+  | Instr (Local_init (v, _, _)) -> Plval (Var v, NoOffset)
+  | Return (Some e, _) | If (e, _, _, _) | Switch (e, _, _, _) -> Pexpr e
+  | _ -> raise Not_found
+
+let probe_code_annot = function
+  | AAssert (_, p) | AInvariant (_, true, p) -> Ppred p.tp_statement
+  | _ -> raise Not_found
+
+let probe_property = function
+  | Property.IPCodeAnnot ica -> probe_code_annot ica.ica_ca.annot_content
+  | IPPropertyInstance { ii_pred = Some pred }
+  | IPPredicate {ip_pred = pred} ->
+    Ppred (Logic_const.pred_of_id_pred pred)
+  | _ -> raise Not_found
+
+let probe_marker = function
+  | Printer_tag.PLval (_, _, lval)
+    when Cil.(isFunctionType (typeOfLval lval)) -> raise Not_found
+  | PVDecl (_, _, vi) when Cil.isFunctionType vi.vtype -> raise Not_found
+  | PLval (_, _, l) -> Plval l
+  | PExp (_, _, e) -> Pexpr e
+  | PStmt (_, s) | PStmtStart (_, s) -> probe_stmt s
+  | PVDecl (_, _, v) -> Plval (Var v, NoOffset)
+  | PTermLval (kf, _, _, tlval) ->
+    Plval (General_requests.term_lval_to_lval kf tlval)
+  | PIP property -> probe_property property
+  | _ -> raise Not_found
 
 let probe marker =
-  let open Printer_tag in
-  match marker with
-  | PLval (_, _, (Var vi, NoOffset)) when Cil.isFunctionType vi.vtype -> None
-  | PLval(_,Kstmt s,l) -> Some (Plval (l,s))
-  | PExp(_,Kstmt s,e) -> Some (Pexpr (e,s))
-  | PStmt(_,s) | PStmtStart(_,s) -> probe_stmt s
-  | PVDecl(_,Kstmt s,v) -> Some (Plval ((Var v,NoOffset),s))
-  | _ -> None
+  try Some (probe_marker marker,
+            General_requests.marker_evaluation_point marker)
+  with Not_found -> None
 
 (* -------------------------------------------------------------------------- *)
 (* --- Stmt Ranking                                                       --- *)
@@ -329,7 +353,8 @@ let filter_variables bases =
 (* -------------------------------------------------------------------------- *)
 
 module type EvaProxy = sig
-  val callstacks : stmt -> callstack list
+  val kf_callstacks : kernel_function -> callstack list
+  val stmt_callstacks : stmt -> callstack list
   val evaluate : probe -> callstack option -> evaluations
 end
 
@@ -346,58 +371,77 @@ module Proxy(A : Analysis.S) : EvaProxy = struct
     let default = fun _ -> Cvalue.V.top in
     Option.value ~default (A.Val.get Main_values.CVal.key)
 
-  let callstacks stmt =
-    match A.get_stmt_state_by_callstack ~after:false stmt with
+  let callstacks get_state_by_callstack elt =
+    match get_state_by_callstack elt with
     | `Top | `Bottom -> []
-    | `Value states -> CSmap.fold_sorted (fun cs _ wcs -> cs :: wcs) states []
+    | `Value states -> CSmap.fold (fun cs _ acc -> cs :: acc) states []
+
+  let kf_callstacks = callstacks A.get_initial_state_by_callstack
+  let stmt_callstacks = callstacks (A.get_stmt_state_by_callstack ~after:false)
 
-  let dstate ~after stmt = function
-    | None -> (A.get_stmt_state ~after stmt :> dstate)
+  let get_state get_consolidated get_by_callstack arg = function
+    | None -> get_consolidated arg
     | Some cs ->
-      match A.get_stmt_state_by_callstack ~selection:[cs] ~after stmt with
+      match get_by_callstack ?selection:(Some [cs]) arg with
       | (`Top | `Bottom) as res -> res
       | `Value cmap ->
         try `Value (CSmap.find cmap cs)
         with Not_found -> `Bottom
 
+  let get_stmt_state ~after =
+    get_state (A.get_stmt_state ~after) (A.get_stmt_state_by_callstack ~after)
+
+  let get_initial_state =
+    get_state A.get_initial_state A.get_initial_state_by_callstack
+
+  let domain_state callstack = function
+    | Initial -> A.get_global_state ()
+    | Pre kf -> get_initial_state kf callstack
+    | Stmt (_, stmt) -> get_stmt_state ~after:false stmt callstack
+
   (* --- Converts an evaluation [result] into an exported [value]. ---------- *)
 
   (* Result of an evaluation: a generic value for scalar types, or an offsetmap
      for struct and arrays. *)
   type result =
-    | Value of A.Val.t
+    | Value of A.Val.t Eval.flagged_value
     | Offsetmap of offsetmap
+    | Status of truth
 
   let pp_result typ fmt = function
-    | Value v -> A.Val.pretty fmt v
+    | Value v -> (Eval.Flagged_Value.pretty (A.Val.pretty_typ (Some typ))) fmt v
     | Offsetmap offsm -> pp_offsetmap typ fmt offsm
+    | Status truth -> Alarmset.Status.pretty fmt truth
 
   let get_pointed_bases = function
-    | Value v -> get_bases (get_cvalue v)
+    | Value v -> get_bases (Bottom.fold ~bottom:Cvalue.V.bottom get_cvalue v.v)
     | Offsetmap offsm -> get_pointed_bases offsm
+    | Status _ -> Base.Hptset.empty
 
-  let get_pointed_markers stmt result =
+  let get_pointed_markers eval_point result =
     let bases = get_pointed_bases result in
     let vars = filter_variables bases in
-    let kf =
-      try Some (Kernel_function.find_englobing_kf stmt)
-      with Not_found -> None
+    let kf, kinstr =
+      match eval_point with
+      | Initial -> None, Kglobal
+      | Pre kf -> Some kf, Kglobal
+      | Stmt (kf, stmt) -> Some kf, Kstmt stmt
     in
     let to_marker vi =
       let text = Pretty_utils.to_string Printer.pp_varinfo vi in
-      let marker = Printer_tag.PLval (kf, Kstmt stmt, Cil.var vi) in
+      let marker = Printer_tag.PLval (kf, kinstr, Cil.var vi) in
       text, marker
     in
     List.map to_marker vars
 
   (* Creates an exported [value] from an evaluation result. *)
-  let make_value typ stmt (result, alarms) =
+  let make_value typ eval_point (result, alarms) =
     let descr = Format.asprintf "@[<hov 2>%a@]" Alarms.pretty in
     let f alarm status acc = (status, descr alarm) :: acc in
     let alarms = Alarmset.fold f [] alarms |> List.rev in
     let pretty_eval = Bottom.pretty (pp_result typ) in
     let value = Pretty_utils.to_string pretty_eval result in
-    let pointed_markers = get_pointed_markers stmt in
+    let pointed_markers = get_pointed_markers eval_point in
     let pointed_vars = Bottom.fold ~bottom:[] pointed_markers result in
     { value; alarms; pointed_vars }
 
@@ -417,13 +461,25 @@ module Proxy(A : Analysis.S) : EvaProxy = struct
   let eval_lval lval state =
     match Cil.(unrollType (typeOfLval lval)) with
     | TInt _ | TEnum _ | TPtr _ | TFloat _ ->
-      A.copy_lvalue state lval >>=. fun value ->
-      value.v >>-: fun v -> Value v
+      A.copy_lvalue state lval >>=: fun value -> Value value
     | _ ->
       lval_to_offsetmap lval state >>=: fun offsm -> Offsetmap offsm
 
   let eval_expr expr state =
-    A.eval_expr state expr >>=: fun value -> Value value
+    A.eval_expr state expr >>=: fun value ->
+    Value { v = `Value value; initialized = true; escaping = false }
+
+  let eval_pred eval_point predicate state =
+    let result =
+      match eval_point with
+      | Initial | Pre _ -> None
+      | Stmt (kf, _) -> Eva_utils.find_return_var kf
+    in
+    let env =
+      Abstract_domain.{ states = (function _ -> A.Dom.top) ; result }
+    in
+    let truth = A.Dom.evaluate_predicate env state predicate in
+    `Value (Status truth), Alarmset.none
 
   (* --- Evaluates all steps (before/after the statement). ------------------ *)
 
@@ -434,32 +490,34 @@ module Proxy(A : Analysis.S) : EvaProxy = struct
       let else_state = (A.assume_cond stmt state cond false :> dstate) in
       Cond (eval then_state, eval else_state)
     | Instr (Set _ | Call _ | Local_init _) ->
-      let after_state = dstate ~after:true stmt callstack in
+      let after_state = get_stmt_state ~after:true stmt callstack in
       After (eval after_state)
     | _ -> Nothing
 
-  let eval_steps typ eval stmt callstack =
+  let eval_steps typ eval eval_point callstack =
     let default value = { value; alarms = []; pointed_vars = []; } in
     let eval = function
       | `Bottom -> default "Unreachable"
       | `Top -> default "No information"
-      | `Value state -> make_value typ stmt (eval state)
+      | `Value state -> make_value typ eval_point (eval state)
     in
-    let before = dstate ~after:false stmt callstack in
+    let before = domain_state callstack eval_point in
     let here = eval before in
     let next =
-      match before with
-      | `Bottom | `Top -> Nothing
-      | `Value state -> do_next eval state stmt callstack
+      match before, eval_point with
+      | `Value state, Stmt (_, stmt) -> do_next eval state stmt callstack
+      | _ -> Nothing
     in
     { here; next; }
 
-  let evaluate p callstack =
-    match p with
-    | Plval (lval, stmt) ->
-      eval_steps (Cil.typeOfLval lval) (eval_lval lval) stmt callstack
-    | Pexpr (expr, stmt) ->
-      eval_steps (Cil.typeOf expr) (eval_expr expr) stmt callstack
+  let evaluate (term, eval_point) callstack =
+    match term with
+    | Plval lval ->
+      eval_steps (Cil.typeOfLval lval) (eval_lval lval) eval_point callstack
+    | Pexpr expr ->
+      eval_steps (Cil.typeOf expr) (eval_expr expr) eval_point callstack
+    | Ppred pred ->
+      eval_steps Cil.intType (eval_pred eval_point pred) eval_point callstack
 end
 
 let proxy =
@@ -481,11 +539,14 @@ let () =
     ~output:(module Jlist(Jcallstack))
     begin fun markers ->
       let module A : EvaProxy = (val proxy ()) in
-      let add stmt = List.fold_right CSet.add (A.callstacks stmt) in
       let gather_callstacks cset marker =
-        match probe marker with
-        | Some (Pexpr (_, stmt) | Plval (_, stmt)) -> add stmt cset
-        | None -> cset
+        let list =
+          match probe marker with
+          | Some (_, Stmt (_, stmt)) -> A.stmt_callstacks stmt
+          | Some (_, Pre kf) -> A.kf_callstacks kf
+          | Some (_, Initial) | None -> []
+        in
+        List.fold_left (fun set elt -> CSet.add elt set) cset list
       in
       let cset = List.fold_left gather_callstacks CSet.empty markers in
       Ranking.sort (CSet.elements cset)
@@ -528,6 +589,11 @@ let () =
 (* --- Request getProbeInfo                                               --- *)
 (* -------------------------------------------------------------------------- *)
 
+let is_reachable = function
+  | Stmt (_, stmt) -> Results.is_reachable stmt
+  | Pre kf -> Results.is_called kf
+  | Initial -> Results.is_reachable_kinstr Kglobal
+
 let () =
   let getProbeInfo = Request.signature ~input:(module Jmarker) () in
   let set_evaluable = Request.result getProbeInfo
@@ -539,9 +605,6 @@ let () =
   and set_stmt = Request.result_opt getProbeInfo
       ~name:"stmt" ~descr:(Md.plain "Probe statement")
       (module Jstmt)
-  and set_rank = Request.result getProbeInfo
-      ~name:"rank" ~descr:(Md.plain "Probe statement rank")
-      ~default:0 (module Jint)
   and set_effects = Request.result getProbeInfo
       ~name:"effects" ~descr:(Md.plain "Effectfull statement")
       ~default:false (module Jbool)
@@ -549,27 +612,30 @@ let () =
       ~name:"condition" ~descr:(Md.plain "Conditional statement")
       ~default:false (module Jbool)
   in
-  let set_probe rq pp p s =
+  let set_probe rq pp p eval_point =
     let computed = Analysis.is_computed () in
-    let reachable = Results.is_reachable s in
+    let reachable = is_reachable eval_point in
     set_evaluable rq (computed && reachable);
-    set_code rq (Some (Pretty_utils.to_string pp p)) ;
-    set_stmt rq (Some s) ;
-    set_rank rq (Ranking.stmt s) ;
+    set_code rq (Some (Pretty_utils.to_string pp p));
+    set_stmt rq (match eval_point with Stmt (_, s) -> Some s | _ -> None);
     let on_steps = function
       | `Here -> ()
       | `Then _ | `Else _ -> set_condition rq true
       | `After -> set_effects rq true
-    in List.iter on_steps (next_steps s)
+    in
+    List.iter on_steps (next_steps eval_point)
   in
   Request.register_sig ~package getProbeInfo
     ~kind:`GET ~name:"getProbeInfo"
     ~descr:(Md.plain "Probe informations")
     begin fun rq marker ->
       match probe marker with
-      | Some (Plval (l, s)) -> set_probe rq Printer.pp_lval l s
-      | Some (Pexpr (e, s)) -> set_probe rq Printer.pp_exp  e s
       | None -> set_evaluable rq false
+      | Some (term, eval_point) ->
+        match term with
+        | Plval l -> set_probe rq Printer.pp_lval l eval_point
+        | Pexpr e -> set_probe rq Printer.pp_exp e eval_point
+        | Ppred p -> set_probe rq Printer.pp_predicate p eval_point
     end
 
 (* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/eva/domains/cvalue/builtins.ml b/src/plugins/eva/domains/cvalue/builtins.ml
index 2f497c83aec2232083a53a68a6bc222679f164e7..feb925ad393094dc7e98d1d4112efe7de8af2af3 100644
--- a/src/plugins/eva/domains/cvalue/builtins.ml
+++ b/src/plugins/eva/domains/cvalue/builtins.ml
@@ -165,9 +165,10 @@ let prepare_builtin kf (name, builtin, cacheable, expected_typ) =
     Self.warning ~source ~once:true
       ~wkey:Self.wkey_builtins_override
       "The builtin %s will not be used for function %a of incompatible type.@ \
-       (got: %a)."
+       (got: %a. Machdep is %s)."
       name Kernel_function.pretty kf
       Printer.pp_typ (Kernel_function.get_type kf)
+      Cil.theMachine.theMachine.machdep_name
   else
     match find_builtin_specification kf with
     | None ->
diff --git a/src/plugins/eva/domains/hcexprs.ml b/src/plugins/eva/domains/hcexprs.ml
index 170011b36caf1961bba12169a7ed64e705736cb8..c9a1d48b3bff48020d873f1a3880afec570b8506 100644
--- a/src/plugins/eva/domains/hcexprs.ml
+++ b/src/plugins/eva/domains/hcexprs.ml
@@ -135,6 +135,10 @@ module HCE = struct
     | E _ -> false
     | LV _ -> true
 
+  let type_of h = match get h with
+    | E e -> Cil.typeOf e
+    | LV lv -> Cil.typeOfLval lv
+
   let replace kind ~late ~heir h = match get h with
     | E e ->
       let e = E.replace kind ~late ~heir e in
diff --git a/src/plugins/eva/domains/hcexprs.mli b/src/plugins/eva/domains/hcexprs.mli
index e39664b4827f696f413c28c62522db515732cbce..5d346bdf9de93bb74d7a49d098f6779b0033bd4f 100644
--- a/src/plugins/eva/domains/hcexprs.mli
+++ b/src/plugins/eva/domains/hcexprs.mli
@@ -55,7 +55,7 @@ module HCE: sig
   val to_exp: t -> exp
   val to_lval: t -> lval option
   val is_lval: t -> bool
-
+  val type_of: t -> typ
 
   (** Replaces all occurrences of the lvalue [late] by the expression [heir].
       @raise NonExchangeable if the replacement is not feasible. *)
diff --git a/src/plugins/eva/domains/octagons.ml b/src/plugins/eva/domains/octagons.ml
index add6bba4fb5a8308fb2702a59dcef0b1caabd941..00adb0b62fdff9fa42f670690688e674271b7a16 100644
--- a/src/plugins/eva/domains/octagons.ml
+++ b/src/plugins/eva/domains/octagons.ml
@@ -52,76 +52,117 @@ type kind = Integer | Float
 
 let typ_kind typ =
   match Cil.unrollType typ with
-  | TInt _ | TEnum  _ -> Integer
+  | TInt _ | TEnum  _ | TPtr _ -> Integer
   | TFloat _ -> Float
   | _ -> assert false
 
+type dependencies = Eva_utils.deps = {
+  data: Locations.Zone.t;
+  indirect: Locations.Zone.t;
+}
+
+type evaluator = Cil_types.exp -> Cvalue.V.t or_top
+
 (* Abstract interface for the variables used by the octagons. *)
 module type Variable = sig
   include Datatype.S_with_collections
-  (* Creates a variable from a varinfo. Should be extended to support more
-     lvalues. *)
-  val make: varinfo -> t
+  (* Creates a variable from a lvalue. *)
+  val make_lval: lval -> t
   val make_int: varinfo -> t
-  (* Returns all variables that may have been created for a varinfo. *)
-  val get_all: varinfo -> t list
+  val make_startof: varinfo -> t
   val kind: t -> kind (* The kind of the variable: integer or float. *)
   val lval: t -> lval option (* The CIL lval corresponding to the variable. *)
-  val base: t -> Base.t (* Base of the variable. *)
   val id: t -> int (* Unique id, needed to use variables as hptmap keys. *)
+  val deps: eval_loc:(Cil_types.lval -> Precise_locs.precise_location) ->
+    t -> dependencies
 end
 
 (* Variables of the octagons. Should be extended later to also include
    symbolic lvalues. *)
 module Variable : Variable = struct
+  module HCE = Hcexprs.HCE
+
   type var =
     | Var of varinfo
     | Int of varinfo
+    | StartOf of varinfo
+    | Lval of HCE.t
+
+  type tt = var * int
+
+  (* The use of [HCE.id] makes this id non-deterministic. This can have an
+     impact when printing the domain state, as the order between variables
+     depends on this id. Option -deterministic circumvents this issue. *)
+  let make_id = function
+    | Var vi -> 4 * vi.vid
+    | Int vi -> 4 * vi.vid + 1
+    | StartOf vi -> 4 * vi.vid + 2
+    | Lval lval -> 4 * HCE.id lval + 3
 
-  let id = function
-    | Var vi -> 2 * vi.vid
-    | Int vi -> 2 * vi.vid + 1
+  let id (_var, id) = id
 
   module Datatype_Input = struct
     include Datatype.Undefined
-    type t = var
+    type t = tt
     let name = "Eva.Octagons.Variable"
     let structural_descr = Structural_descr.t_abstract
-    let reprs = [ Var (List.hd Cil_datatype.Varinfo.reprs) ]
-
-    let compare x y =
-      match x, y with
-      | Var x, Var y
-      | Int x, Int y -> Cil_datatype.Varinfo.compare x y
-      | Var _, Int _ -> -1
-      | Int _, Var _ -> 1
-
-    let equal x y = compare x y = 0
+    let reprs = [ Var (List.hd Cil_datatype.Varinfo.reprs), 0 ]
 
+    let compare x y = id y - id x
+    let equal = Datatype.from_compare
     let hash = id
     let rehash = Datatype.identity
 
-    let pretty fmt = function
-      | Var vi -> Printer.pp_varinfo fmt vi
+    let pretty fmt (var, _id) =
+      match var with
+      | Var vi | StartOf vi -> Printer.pp_varinfo fmt vi
       | Int vi -> Format.fprintf fmt "(integer)%a" Printer.pp_varinfo vi
+      | Lval lval -> HCE.pretty fmt lval
+
   end
 
   include Datatype.Make_with_collections (Datatype_Input)
-  let make vi = Var vi
-  let make_int vi = Int vi
-  let get_all vi = [ Var vi; Int vi ]
 
-  let kind = function
+  let make var = var, make_id var
+
+  let make_lval = function
+    | Cil_types.Var vi, NoOffset -> make (Var vi)
+    | lval -> make (Lval (HCE.of_lval lval))
+
+  let make_int vi = make (Int vi)
+  let make_startof vi = make (StartOf vi)
+
+  let kind (var, _) =
+    match var with
     | Var vi -> typ_kind vi.vtype
-    | Int _ -> Integer
+    | Int _ | StartOf _ -> Integer
+    | Lval lval -> typ_kind (HCE.type_of lval)
 
-  let lval = function
+  let lval (var, _) =
+    match var with
     | Var vi -> Some (Cil_types.Var vi, NoOffset)
-    | Int _ -> None
-
-  let base = function Var vi | Int vi -> Base.of_varinfo vi
+    | Lval lval -> HCE.to_lval lval
+    | Int _ | StartOf _ -> None
+
+  let deps ~eval_loc (var, _) =
+    match var with
+    | Var vi | Int vi ->
+      {
+        data = Locations.zone_of_varinfo vi;
+        indirect = Locations.Zone.bottom;
+      }
+    | StartOf _ ->
+      { data = Locations.Zone.bottom ; indirect = Locations.Zone.bottom }
+    | Lval lval ->
+      Eva_utils.deps_of_lval eval_loc (Option.get (HCE.to_lval lval))
 end
 
+module VarSet =
+  Hptset.Make
+    (Variable)
+    (struct let v = [ [ ] ] end)
+    (struct let l = [ Ast.self ] end)
+
 (* Pairs of related variables in an octagon.
    This module imposes an order between the two variables X and Y in a pair
    to avoid creating octagons about X±Y *and* about Y±X. *)
@@ -147,12 +188,19 @@ module Pair = struct
 
   let fst t = fst (get t)
   let kind t = Variable.kind (fst t)
+  let variable_list t =
+    let (v1,v2) = get t in [v1 ; v2]
 end
 
 
 (* Kind of relation between two variables X and Y: X+Y or X-Y. *)
 type operation = Add | Sub
 
+let operation_of_binop = function
+  | PlusA | PlusPI -> Add
+  | MinusA | MinusPI | MinusPP -> Sub
+  | _ -> assert false
+
 (* Extended arithmetic operations over Ival.t. *)
 module Arith = struct
   open Ival
@@ -188,6 +236,7 @@ module Arith = struct
 
   let sub = int_or_float_operation Ival.sub_int Fval.sub
   let add = int_or_float_operation Ival.add_int Fval.add
+  let mul_integer = Ival.scale
 
   let apply = function
     | Add -> add
@@ -218,6 +267,13 @@ let _pretty_octagon fmt octagon =
     Variable.pretty x op Variable.pretty y
     (Unicode.inset_string ()) Ival.pretty octagon.value
 
+(* An environment associates a term v ± c, where v is a variable and
+   c an integer limited to an interval, to some well chosen expressions. A
+   request to the environment may return a new or an existing variable.
+   The abstract domain chooses which expressions are worth being represented
+   by a variable; the environment may return [None] otherwise. *)
+type environment = Cil_types.exp -> (Variable.t * Ival.t) option
+
 (* Transforms Cil expressions into mathematical octagons.
    Use Ival.t to evaluate expressions. *)
 module Rewriting = struct
@@ -253,32 +309,46 @@ module Rewriting = struct
      where X is a variable and coeff an interval. *)
   type var_coeff = { var: Variable.t; sign: bool; coeff: Ival.t; }
 
+  let _pretty_var_coeff fmt var_coeff =
+    Format.fprintf fmt "%s%a - %a"
+      (if var_coeff.sign then "" else "-")
+      Variable.pretty var_coeff.var
+      Ival.pretty var_coeff.coeff
+
   (* Negates a simplified form. *)
   let neg { var; sign; coeff } =
     { var; sign = not sign; coeff = Arith.neg coeff }
 
-  (* Is the interval computed for a variable a singleton? *)
-  let is_singleton = function
-    | `Top -> false
-    | `Value ival -> Ival.cardinal_zero_or_one ival
-
   (* If a needed interval is unknown, stop the current computation and return
      an empty list. *)
-  let (>>) value f = match value with
+  let (let*) x f = match x with
     | `Top -> []
-    | `Value ival -> f ival
+    | `Value x -> f x
+
+  let project_ival x =
+    match x with
+    | `Top -> `Top
+    | `Value x ->
+      try
+        `Value (Cvalue.V.project_ival x)
+      with Cvalue.V.Not_based_on_null -> `Top
 
   (* Apply [f typ v1 v2] if the operation [e1 op e2] does not overflow,
      where [v1] and [v2] are the intervals for [e1] and [e2], and [typ] is
      the type of [e1]. Returns the empty list otherwise. *)
-  let apply_binop f evaluate typ e1 op e2 =
-    evaluate e1 >> fun v1 ->
-    evaluate e2 >> fun v2 ->
+  let apply_binop f (eval : evaluator) typ e1 op e2 =
     let kind = typ_kind (Cil.typeOf e1) in
-    let result = Arith.apply op kind v1 v2 in
-    if may_overflow typ result
-    then []
-    else f kind v1 v2
+    let v1 = eval e1 in
+    let v2 = eval e2 in
+    if Cil.isPointerType typ
+    then f kind v1 v2
+    else
+      let* v1' = project_ival v1 in
+      let* v2' = project_ival v2 in
+      let result = Arith.apply op kind v1' v2' in
+      if may_overflow typ result
+      then []
+      else f kind v1 v2
 
   (* Rewrites the Cil expression [expr] into the simplified form [±x-coeff],
      where [x] is a non-singleton variable and [coeff] is an interval. The
@@ -289,60 +359,63 @@ module Rewriting = struct
      function relies on an evaluation function linking each sub-expression into
      an interval, used for computing sound coefficients. The evaluation may
      return Top for some sub-expression, thus preventing the computation. *)
-  let rec rewrite evaluate expr =
-    match expr.enode with
-    | Lval (Var varinfo, NoOffset) ->
-      if Cil.isIntegralType varinfo.vtype
-      && not (Cil.typeHasQualifier "volatile" varinfo.vtype)
-      && not (is_singleton (evaluate expr))
-      then
-        let var = Variable.make varinfo in
-        [ { var; sign = true; coeff = Ival.zero } ]
-      else []
-
-    | UnOp (Neg, e, typ) ->
-      evaluate e >> fun v ->
-      if may_overflow typ (Arith.neg v)
-      then [] else List.map neg (rewrite evaluate e)
-
-    | BinOp ((PlusA | MinusA as binop), e1, e2, typ) ->
-      let op = if binop = PlusA then Add else Sub in
-      let rewrite_binop typ v1 v2 =
-        let inverse_op = if binop = PlusA then Arith.sub else Arith.add in
-        let add_v2 var =
-          { var with coeff = inverse_op typ var.coeff v2 }
-        in
-        let add_v1 var =
-          let var = if binop = MinusA then neg var else var in
-          { var with coeff = Arith.sub typ var.coeff v1 }
+  let rec rewrite (eval : evaluator) (env : environment) expr =
+    match env expr with
+    | Some (var, ival) -> [ { var; sign = true; coeff = Ival.neg_int ival } ]
+    | None ->
+      match expr.enode with
+      | UnOp (Neg, e, typ) ->
+        let* v = project_ival (eval e) in
+        if may_overflow typ (Arith.neg v)
+        then [] else List.map neg (rewrite eval env e)
+
+      | BinOp (PlusA | MinusA | PlusPI | MinusPI as binop, e1, e2, typ) ->
+        let op = operation_of_binop binop in
+        let rewrite_binop kind v1 v2 =
+          let left_linearized =
+            let* v2 = project_ival v2 in
+            let inverse_op = if op = Add then Arith.sub else Arith.add in
+            try
+              let v2 =
+                if Cil.isPointerType typ
+                then
+                  let scale = Cil.(bytesSizeOf (typeOf_pointed typ)) in
+                  Arith.mul_integer (Integer.of_int scale) v2
+                else v2
+              in
+              let add_v2 var =
+                { var with coeff = inverse_op kind var.coeff v2 }
+              in
+              List.map add_v2 (rewrite eval env e1)
+            with Cil.SizeOfError _ -> []
+          and right_linearized =
+            let* v1 = project_ival v1 in
+            let add_v1 var =
+              let var = if op = Sub then neg var else var in
+              { var with coeff = Arith.sub kind var.coeff v1 }
+            in
+            List.map add_v1 (rewrite eval env e2)
+          in
+          left_linearized @ right_linearized
         in
-        List.map add_v2 (rewrite evaluate e1) @
-        List.map add_v1 (rewrite evaluate e2)
-      in
-      apply_binop rewrite_binop evaluate typ e1 op e2
-
-    | CastE (typ, { enode = Lval (Var vi, NoOffset) })
-      when Cil.isIntegralType typ
-        && Cil.isFloatingType vi.vtype
-        && not (Cil.typeHasQualifier "volatile" vi.vtype)
-        && not (is_singleton (evaluate expr)) ->
-      let var = Variable.make_int vi in
-      [ { var; sign = true; coeff = Ival.zero } ]
+        apply_binop rewrite_binop eval typ e1 op e2
 
+      | CastE (typ, e) ->
+        if Cil.(isIntegralType typ && isIntegralType (typeOf e)) then
+          let* v = project_ival (eval e) in
+          if may_overflow ~cast:true typ v then [] else rewrite eval env e
+        else if Cil.(isPointerType typ && isPointerType (typeOf e)) then
+          rewrite eval env e
+        else
+          []
 
-    | CastE (typ, e) ->
-      if Cil.(isIntegralType typ && isIntegralType (typeOf e)) then
-        evaluate e >> fun v ->
-        if may_overflow ~cast:true typ v then [] else rewrite evaluate e
-      else []
-
-    | _ -> []
+      | _ -> []
 
   (* Rewrites the operation [e1 ± e2] into equivalent octagons ±(X±Y-value). *)
-  let rewrite_binop evaluate e1 binop e2 =
+  let rewrite_binop (eval : evaluator) (env : environment) e1 binop e2 =
     let kind = typ_kind (Cil.typeOf e1) in
-    let vars1 = rewrite evaluate e1 in
-    let vars2 = rewrite evaluate e2 in
+    let vars1 = rewrite eval env e1 in
+    let vars2 = rewrite eval env e2 in
     let vars2 = if binop = Sub then List.map neg vars2 else vars2 in
     let aux acc var1 var2 =
       if Variable.equal var1.var var2.var
@@ -373,10 +446,10 @@ module Rewriting = struct
 
   (* Transforms the constraint [expr] ∈ [ival] into a list of octagonal
      constraints. *)
-  let make_octagons evaluate expr ival =
+  let make_octagons evaluate env expr ival =
     let make_octagons_from_binop kind e1 op e2 ival =
       (* equivalent octagonal forms ±(X±Y-v) for [e1 op e2]. *)
-      let rewritings = rewrite_binop evaluate e1 op e2 in
+      let rewritings = rewrite_binop evaluate env e1 op e2 in
       (* create the final octagon, knowning that [e1 op e2] ∈ [ival]. *)
       let make_octagon (sign, octagon) =
         let ival = if sign then ival else Arith.neg ival in
@@ -386,13 +459,13 @@ module Rewriting = struct
       List.map make_octagon rewritings
     in
     match expr.enode with
-    | BinOp ((PlusA | MinusA as binop), e1, e2, typ) ->
-      let op = if binop = PlusA then Add else Sub in
+    | BinOp (PlusA | MinusA | PlusPI | MinusPI | MinusPP as binop, e1, e2, typ) ->
+      let op = operation_of_binop binop in
       let make_octagons typ _ _ = make_octagons_from_binop typ e1 op e2 ival in
       apply_binop make_octagons evaluate typ e1 op e2
     | BinOp ((Lt | Gt | Le | Ge | Eq | Ne as binop), e1, e2, _typ) ->
       let typ = Cil.typeOf e1 in
-      if not (Cil.isIntegralType typ)
+      if not (Cil.isIntegralOrPointerType typ)
       || (Ival.contains_zero ival && Ival.contains_non_zero ival)
       then []
       else
@@ -429,7 +502,7 @@ module Rewriting = struct
   (* Evaluates the Cil expression [expr], by rewriting it into octagonal
      constraints using [evaluate_expr] to evaluate sub-expressions, and
      then using [evaluate_octagon] to evaluate the octagons. *)
-  let evaluate_through_octagons evaluate_expr evaluate_octagon expr =
+  let evaluate_through_octagons (eval : evaluator) evaluate_octagon env expr =
     let evaluate_octagon acc (sign, octagon) =
       match evaluate_octagon octagon with
       | None -> acc
@@ -444,12 +517,14 @@ module Rewriting = struct
     match expr.enode with
     | BinOp ((PlusA | MinusA as binop), e1, e2, typ) ->
       let op = if binop = PlusA then Add else Sub in
-      let octagons = rewrite_binop evaluate_expr e1 op e2 in
+      let octagons = rewrite_binop eval env e1 op e2 in
       let ival = evaluate_octagons octagons in
       if Ival.(equal top ival) then default else
         let kind = typ_kind (Cil.typeOf e1) in
         let ival2 =
-          match evaluate_expr e1, evaluate_expr e2 with
+          match
+            project_ival (eval e1), project_ival (eval e2)
+          with
           | `Value v1, `Value v2 -> Arith.apply op kind v1 v2
           | _, _ -> Ival.top
         in
@@ -458,12 +533,12 @@ module Rewriting = struct
         then default
         else ival, overflow_alarms typ expr ival
     | BinOp ((Lt | Gt | Le | Ge | Eq as binop), e1, e2, _typ)
-      when Cil.isIntegralType (Cil.typeOf e1) ->
+      when Cil.isIntegralOrPointerType (Cil.typeOf e1) ->
       let comp = Eva_utils.conv_comp binop in
       (* Evaluate [e1 - e2] and compare the resulting interval to the interval
          for which the comparison [e1 # e2] holds. *)
       let range = comparison_range comp in
-      let octagons = rewrite_binop evaluate_expr e1 Sub e2 in
+      let octagons = rewrite_binop eval env e1 Sub e2 in
       let ival = evaluate_octagons octagons in
       if Ival.is_included ival range then Ival.one, Alarmset.all
       else if not (Ival.intersects ival range)
@@ -670,29 +745,29 @@ module Relations = struct
   module Dependencies = struct let l = [ Ast.self ] end
 
   include Hptmap.Make (Variable)
-      (struct include Variable.Set let pretty_debug = pretty end)
+      (struct include VarSet let pretty_debug = pretty end)
       (Hptmap.Comp_unused) (Initial_Values) (Dependencies)
 
   let inter =
     let cache = Hptmap_sig.PersistentCache "Octagons.Relations.inter" in
     let decide _pair x y =
-      let r = Variable.Set.inter x y in
-      if Variable.Set.is_empty r then None else Some r
+      let r = VarSet.inter x y in
+      if VarSet.is_empty r then None else Some r
     in
     inter ~cache ~symmetric:true ~idempotent:true ~decide
 
   let union =
     let cache = Hptmap_sig.PersistentCache "Octagons.Relations.union" in
-    let decide _pair x y = Variable.Set.union x y in
+    let decide _pair x y = VarSet.union x y in
     join ~cache ~symmetric:true ~idempotent:true ~decide
 
   (* Marks y as related to x. *)
   let relate_aux x y t =
     let related =
       try find x t
-      with Not_found -> Variable.Set.empty
+      with Not_found -> VarSet.empty
     in
-    let updated = Variable.Set.add y related in
+    let updated = VarSet.add y related in
     add x updated t
 
   (* Marks x and y as mutually related. *)
@@ -701,7 +776,7 @@ module Relations = struct
     relate_aux y x (relate_aux x y t)
 
   let add variable set t =
-    if Variable.Set.is_empty set
+    if VarSet.is_empty set
     then remove variable t
     else add variable set t
 end
@@ -759,6 +834,315 @@ module Intervals = struct
     inter ~cache ~symmetric:false ~idempotent:true ~decide
 end
 
+
+(* -------------------------------------------------------------------------- *)
+(*                               Dependencies                                 *)
+(* -------------------------------------------------------------------------- *)
+
+module VariableToDeps =
+struct
+  module Deps =
+  struct
+    include Function_Froms.Deps
+    let pretty_debug = pretty_precise
+  end
+
+  let cache_prefix = "Eva.Octagons.VariableToDeps"
+
+  include Hptmap.Make (Variable) (Deps) (Hptmap.Comp_unused)
+      (struct let v = [[]] end) (struct let l = [Ast.self] end)
+
+  let is_included: t -> t -> bool =
+    let cache_name = cache_prefix ^ ".is_included" in
+    let decide_fst _b _v1 = true in
+    let decide_snd _b _v2 = false in
+    let decide_both _ v1 v2 = Deps.is_included v1 v2 in
+    let decide_fast s t = if s == t then PTrue else PUnknown in
+    binary_predicate
+      (Hptmap_sig.PersistentCache cache_name) UniversalPredicate
+      ~decide_fast ~decide_fst ~decide_snd ~decide_both
+
+  let narrow: t -> t -> t =
+    let cache_name = cache_prefix ^ ".narrow" in
+    let cache = Hptmap_sig.PersistentCache cache_name in
+    let symmetric = true in
+    let idempotent = true in
+    let decide _ v1 v2 = Deps.narrow v1 v2 in
+    join ~cache ~symmetric ~idempotent ~decide
+
+  let join: t -> t -> t =
+    let cache_name = cache_prefix ^ ".join" in
+    let cache = Hptmap_sig.PersistentCache cache_name in
+    let symmetric = true in
+    let idempotent = true in
+    let decide _ v1 v2 = Some (Deps.join v1 v2) in
+    inter ~cache ~symmetric ~idempotent ~decide
+
+  let find_opt (v: Variable.t) (m: t) =
+    try Some (find v m) with Not_found -> None
+
+  (* Return the subtrees of the left map whose keys are not in the right map. *)
+  let only_in_left =
+    let cache_name = cache_prefix ^ ".only_in_left" in
+    let cache = Hptmap_sig.PersistentCache cache_name in
+    let symmetric = false in
+    let idempotent = false in
+    let decide_both _ _ _ = None in
+    let decide_left = Neutral in
+    let decide_right = Absorbing in
+    merge ~cache ~symmetric ~idempotent ~decide_both ~decide_left ~decide_right
+
+  let all_but_diff =
+    let cache_name = cache_prefix ^ ".all_but_diff" in
+    let cache = Hptmap_sig.PersistentCache cache_name in
+    let decide_both _ d1 d2 = if Deps.equal d1 d2 then Some d1 else None in
+    merge ~cache ~symmetric:true ~idempotent:true
+      ~decide_left:Neutral ~decide_right:Neutral ~decide_both
+end
+
+module BaseToVariables = struct
+  module VSet = VarSet
+
+  (* [BaseToVariables] represents a map from bases to each symbolic variable
+     used in the domain state that depends on this base.
+     These variables are split into two (non necessary disjoint) sets:
+     - direct dependency: variables whose value depends on the base;
+     - indirect dependency: variables whose location depends on the base. *)
+  module VSetPair =
+  struct
+    include Datatype.Pair
+        (VSet) (* Directly dependent variables *)
+        (VSet) (* Indirectly dependent variables *)
+    let pretty_debug = pretty
+    let inter (s1,t1) (s2,t2) = VSet.inter s1 s2, VSet.inter t1 t2
+    let union (s1,t1) (s2,t2) = VSet.union s1 s2, VSet.union t1 t2
+    let is_empty (s, t) = VSet.is_empty s && VSet.is_empty t
+  end
+
+  include Hptmap.Make (Base.Base) (VSetPair) (Hptmap.Comp_unused)
+      (struct let v = [[]] end) (struct let l = [Ast.self] end)
+
+  let cache_prefix = "Eva.Octagons.BaseToVariables"
+
+  let _narrow =
+    let cache_name = cache_prefix ^ ".narrow" in
+    let cache = Hptmap_sig.PersistentCache cache_name in
+    let symmetric = true in
+    let idempotent = true in
+    let decide _ v1 v2 =
+      let inter = VSetPair.inter v1 v2 in
+      if VSetPair.is_empty inter then None else Some inter
+    in
+    inter ~cache ~symmetric ~idempotent ~decide
+
+  let join =
+    let cache_name = cache_prefix ^ ".join" in
+    let cache = Hptmap_sig.PersistentCache cache_name in
+    let symmetric = true in
+    let idempotent = true in
+    let decide _ v1 v2 = VSetPair.union v1 v2 in
+    join ~cache ~symmetric ~idempotent ~decide
+
+  let find b m =
+    try find b m
+    with Not_found -> VSet.empty, VSet.empty
+
+  let add_direct v =
+    replace (function
+        | None -> Some (VSet.singleton v, VSet.empty)
+        | Some (direct, indirect) -> Some (VSet.add v direct, indirect))
+
+  let add_indirect v =
+    replace (function
+        | None -> Some (VSet.empty, VSet.singleton v)
+        | Some (direct, indirect) -> Some (direct, VSet.add v indirect))
+
+  let add_deps var deps map =
+    Locations.Zone.fold_bases (add_direct var) deps.data map |>
+    Locations.Zone.fold_bases (add_indirect var) deps.indirect
+
+  let remove_direct v =
+    replace (function
+        | None -> None
+        | Some (direct, indirect) ->
+          let direct = VSet.remove v direct in
+          if VSet.is_empty direct && VSet.is_empty indirect
+          then None
+          else Some (direct, indirect))
+
+  let remove_indirect v =
+    replace (function
+        | None -> None
+        | Some (direct, indirect) ->
+          let indirect = VSet.remove v indirect in
+          if VSet.is_empty direct && VSet.is_empty indirect
+          then None
+          else Some (direct, indirect))
+
+  let remove_deps var deps map =
+    Locations.Zone.fold_bases (remove_direct var) deps.data map |>
+    Locations.Zone.fold_bases (remove_indirect var) deps.indirect
+
+  let all_variables m =
+    fold (fun _b (dv, iv) acc -> VSet.(union (union dv iv) acc)) m VSet.empty
+end
+
+module Deps = struct
+  module VSet = VarSet
+
+  include Datatype.Pair (VariableToDeps) (BaseToVariables)
+
+  (* [hash] and [compare] do not need to consider the [BaseToVariables] part as
+     it can be fully deduced from VariableToDeps's one *)
+  let hash (m, _i: t) =
+    VariableToDeps.hash m
+
+  let compare (m1, _i1: t) (m2, _i2: t) =
+    VariableToDeps.compare m1 m2
+
+  let empty = VariableToDeps.empty, BaseToVariables.empty
+
+  let intersects_base (_m, i: t) base =
+    let data, indirect = BaseToVariables.find base i in
+    VSet.union data indirect |> VSet.elements
+
+  let intersects_var (d: t) (vi: Cil_types.varinfo) =
+    intersects_base d (Base.of_varinfo vi)
+
+  let intersects_zone (m, i: t) zone =
+    let filter ~direct zone v =
+      try
+        let deps = VariableToDeps.find v m in
+        let v_zone = if direct then deps.data else deps.indirect in
+        Locations.Zone.intersects v_zone zone
+      with Not_found -> false
+    in
+    let get_at_base b intervals (data_acc, indirect_acc) =
+      let data, indirect = BaseToVariables.find b i in
+      let zone = Locations.Zone.inject b intervals in
+      VSet.union data_acc (VSet.filter (filter ~direct:true zone) data),
+      VSet.union indirect_acc (VSet.filter (filter ~direct:false zone) indirect)
+    in
+    let data, indirect =
+      Locations.Zone.fold_topset_ok get_at_base zone (VSet.empty, VSet.empty)
+    in
+    VSet.union data indirect |> VSet.elements
+
+  (* Does [deps] contains at least the bases from [previous_deps]? *)
+  let are_bases_increasing previous_deps deps =
+    let get_bases = Locations.Zone.get_bases in
+    let is_increasing previous_zone zone =
+      Base.SetLattice.is_included (get_bases previous_zone) (get_bases zone)
+    in
+    is_increasing previous_deps.data deps.data &&
+    is_increasing previous_deps.indirect deps.indirect
+
+  (* Exact but slower [add]: in the resulting maps (m, i), [i] is exactly the
+     inverse of the map [m]. *)
+  let _exact_add var deps (m, i: t): t =
+    let add_to (m, i) =
+      VariableToDeps.add var deps m,
+      BaseToVariables.add_deps var deps i
+    in
+    match VariableToDeps.find_opt var m with
+    | Some previous_deps when Function_Froms.Deps.equal previous_deps deps ->
+      m, i
+    | Some previous_deps when not (are_bases_increasing previous_deps deps) ->
+      (* If [var] already exists in the state and had bigger dependencies (a
+         dependency can disappear by reduction), remove the previous deps
+         from the inverse map to ensure consistency between both maps. *)
+      add_to (m, BaseToVariables.remove_deps var previous_deps i)
+    | _ -> add_to (m, i)
+
+  (* Faster but approximating [add]: in the resulting maps (m, i), [i] may
+     contain variables that do not appear in [m]. *)
+  let add var deps (m, i: t): t =
+    match VariableToDeps.find_opt var m with
+    | Some d when Function_Froms.Deps.equal d deps -> m, i
+    | _ ->
+      VariableToDeps.add var deps m,
+      BaseToVariables.add_deps var deps i
+
+  let remove (var: Variable.t) ((m, i): t): t option =
+    match VariableToDeps.find_opt var m with
+    | None -> None (* The variable was not registered *)
+    | Some deps ->
+      Some (VariableToDeps.remove var m,
+            BaseToVariables.remove_deps var deps i)
+
+  let filter (bases: Base.Hptset.t) (m, i : t): VSet.t * t =
+    let i_inter, i_diff = BaseToVariables.partition_with_shape bases i in
+    let removed_vars = BaseToVariables.all_variables i_diff in
+    let m = VariableToDeps.diff_with_shape removed_vars m in
+    let filter (s1, s2) =
+      VSet.diff s1 removed_vars, VSet.diff s2 removed_vars
+    in
+    let i = BaseToVariables.map filter i_inter in
+    removed_vars, (m, i)
+
+  let get_var_bases (m, _: t) (var: Variable.t) =
+    try
+      let deps = VariableToDeps.find var m in
+      let zone = Locations.Zone.join deps.data deps.indirect in
+      Locations.Zone.get_bases zone
+    with Not_found -> Base.SetLattice.empty
+
+  (* Exact but slower [join]: in the resulting maps (m, i), [i] is exactly the
+     inverse of the map [m]. *)
+  let _exact_join (m1, i1: t) (m2, i2: t) =
+    let m1_only = VariableToDeps.only_in_left m1 m2
+    and m2_only = VariableToDeps.only_in_left m2 m1 in
+    let i1 = VariableToDeps.fold BaseToVariables.remove_deps m1_only i1
+    and i2 = VariableToDeps.fold BaseToVariables.remove_deps m2_only i2 in
+    VariableToDeps.join m1 m2, BaseToVariables.join i1 i2
+
+  (* Exact but slower [narrow]: in the resulting maps (m, i), [i] is exactly the
+     inverse of the map [m]. *)
+  let _exact_narrow (m1, i1: t) (m2, i2: t) =
+    let all_but_diff = VariableToDeps.all_but_diff m1 m2 in
+    let m1 = VariableToDeps.only_in_left m1 all_but_diff
+    and m2 = VariableToDeps.only_in_left m2 all_but_diff in
+    let m_narrow = VariableToDeps.narrow m1 m2
+    and m_join = VariableToDeps.join m1 m2 in
+    let m = VariableToDeps.narrow m_narrow all_but_diff in
+    let i = BaseToVariables.join i1 i2 in
+    let i = VariableToDeps.fold BaseToVariables.remove_deps m_join i in
+    let i = VariableToDeps.fold BaseToVariables.add_deps m_narrow i in
+    m, i
+
+  (* Faster but approximating [join]: in the resulting maps (m, i), [i] may
+     contain variables that do not appear in [m]. *)
+  let join (m1, i1: t) (m2, i2: t) =
+    VariableToDeps.join m1 m2, BaseToVariables.join i1 i2
+
+  (* Faster but approximating [narrow]: in the resulting maps (m, i), [i] may
+     contain variables that do not appear in [m]. *)
+  let narrow (m1, i1: t) (m2, i2: t) =
+    VariableToDeps.narrow m1 m2, BaseToVariables.join i1 i2
+
+  let is_included (m1, _: t) (m2, _: t) =
+    VariableToDeps.is_included m1 m2
+
+  (* Check inverse dependencies. *)
+  let check (abort: ('a, Format.formatter, unit) format -> 'a) (m, i: t) =
+    let check_inverse var deps =
+      let check_base fst_or_snd base =
+        if not (VSet.mem var (fst_or_snd (BaseToVariables.find base i)))
+        then
+          abort "Missing inverse dependency %a of variable %a@"
+            Base.pretty base Variable.pretty var
+      in
+      let check_zone fst_or_snd zone =
+        let bases = Locations.Zone.get_bases zone in
+        Base.SetLattice.iter (check_base fst_or_snd) bases
+      in
+      check_zone fst deps.data;
+      check_zone snd deps.indirect;
+    in
+    VariableToDeps.iter check_inverse m
+end
+
+
 (* -------------------------------------------------------------------------- *)
 (*                               Octagon states                               *)
 (* -------------------------------------------------------------------------- *)
@@ -772,6 +1156,7 @@ module State = struct
       intervals: Intervals.t;     (* The intervals for the variables X,Y… *)
       relations: Relations.t;     (* The related variables in [octagons]. *)
       modified: Locations.Zone.t; (* The memory zone modified by a function. *)
+      deps: Deps.t;
     }
 
   include Datatype.Make_with_collections
@@ -785,26 +1170,31 @@ module State = struct
             [| Octagons.packed_descr;
                Intervals.packed_descr;
                Relations.packed_descr;
-               Zone.packed_descr |]
+               Zone.packed_descr;
+               Deps.packed_descr |]
         let reprs =
           [ { octagons = Octagons.top;
               intervals = Intervals.empty;
               relations = Relations.empty;
-              modified = Zone.bottom } ]
+              modified = Zone.bottom;
+              deps = Deps.empty; } ]
 
         let compare s1 s2 =
-          let c = Octagons.compare s1.octagons s2.octagons in
-          if c <> 0 then c else
-            let c = Intervals.compare s1.intervals s2.intervals in
-            if c <> 0 then c else
-              Zone.compare s1.modified s2.modified
+          let (<?>) c lcmp =
+            if c <> 0 then c else Lazy.force lcmp
+          in
+          Octagons.compare s1.octagons s2.octagons <?>
+          lazy (Intervals.compare s1.intervals s2.intervals) <?>
+          lazy (Zone.compare s1.modified s2.modified) <?>
+          lazy (Deps.compare s1.deps s2.deps)
 
         let equal = Datatype.from_compare
 
         let hash t =
           Hashtbl.hash (Octagons.hash t.octagons,
                         Intervals.hash t.intervals,
-                        Zone.hash t.modified)
+                        Zone.hash t.modified,
+                        Deps.hash t.deps)
 
         let pretty fmt { octagons } =
           Format.fprintf fmt "@[%a@]" Octagons.pretty octagons
@@ -812,33 +1202,56 @@ module State = struct
 
   let log_category = Self.register_category "d-octagon"
 
-  let pretty_debug fmt { octagons; intervals; relations } =
-    Format.fprintf fmt "@[<v> Octagons: %a@; Intervals: %a@; Relations: %a@]"
+  let pretty_debug fmt { octagons; intervals; relations; deps } =
+    Format.fprintf fmt
+      "@[<v> Octagons: %a@; Intervals: %a@; Relations: %a@; Dependencies: %a@.]"
       Octagons.pretty octagons Intervals.pretty intervals
       Relations.pretty relations
+      Deps.pretty deps
 
   (* Verify the internal structure of a state [t], depending on the boolean
      variable [debug]. *)
   let check =
     if not debug
     then fun _ t -> t
-    else fun msg t ->
+    else fun name t ->
+      let abort format =
+        Format.kasprintf
+          (fun s ->
+             Self.fatal
+               "Incorrect octagon computed by function %s: %s@\n  State: %a"
+               name s pretty_debug t)
+          format
+      in
       (* Checks that an octagon is properly registered in [t.relations]. This is
          mandatory for the soundness of the domain. On the other hand, two
          variables can be related in [t.relations] without an actual octagon
          between them. *)
+      let check_relation x y =
+        try VarSet.mem x (Relations.find y t.relations)
+            && VarSet.mem y (Relations.find x t.relations)
+        with Not_found -> false
+      in
+      let check_relation x y =
+        if not (check_relation x y)
+        then
+          abort "missing relations between %a and %a"
+            Variable.pretty x Variable.pretty y
+      in
+      (* Checks that dependencies of [var] are correctly registered. *)
+      let check_deps var =
+        if not (VariableToDeps.mem var (fst t.deps))
+        then abort "missing dependencies of variable %a" Variable.pretty var
+      in
       let check_octagon pair _ =
         let x, y = Pair.get pair in
-        try Variable.Set.mem x (Relations.find y t.relations)
-            && Variable.Set.mem y (Relations.find x t.relations)
-        with Not_found -> false
+        check_relation x y; check_deps x; check_deps y
       in
-      if Octagons.for_all check_octagon t.octagons
-      then t
-      else
-        Self.abort
-          "Incorrect octagon state computed by function %s:@ %a"
-          msg pretty_debug t
+      Octagons.iter check_octagon t.octagons;
+      Intervals.iter (fun var _ -> check_deps var) t.intervals;
+      (* Check consistency of the dependency maps. *)
+      Deps.check abort t.deps;
+      t
 
   (* Is an octagon no more precise than the intervals inferred for the related
      variables? If so, do not save the octagon in the domain. *)
@@ -858,24 +1271,84 @@ module State = struct
     is_redundant intervals {variables; operation = Add; value = diamond.add} &&
     is_redundant intervals {variables; operation = Sub; value = diamond.sub}
 
+  (* Evaluates offset to an interval using the evaluate function for indexes *)
+  let rec offset_to_coeff (eval : evaluator) base_type offset =
+    let open Lattice_bounds.Top.Operators in
+    match offset with
+    | Cil_types.NoOffset -> `Value (Ival.zero)
+    | Field (fi, sub) ->
+      let* sub_coeff = offset_to_coeff eval fi.ftype sub in
+      begin try
+          let byte_offset = Integer.of_int (fst (Cil.fieldBitsOffset fi) / 8) in
+          let coeff = Ival.add_singleton_int byte_offset sub_coeff in
+          `Value coeff
+        with Cil.SizeOfError _ -> `Top
+      end
+    | Index (exp, sub) ->
+      let elem_type = Cil.typeOf_array_elem base_type in
+      let* cvalue = eval exp in
+      let* index =
+        try
+          `Value (Cvalue.V.project_ival cvalue)
+        with Cvalue.V.Not_based_on_null -> `Top
+      in
+      let* sub_coeff = offset_to_coeff eval elem_type sub in
+      let+ elem_size =
+        try `Value (Cil.bytesSizeOf elem_type)
+        with Cil.SizeOfError _ -> `Top
+      in
+      Ival.(add_int (scale (Integer.of_int elem_size) index) sub_coeff)
+
+  let mk_variable_builder (eval : evaluator) (_: t) =
+    let (let*) x f = Option.bind (Top.to_option x) f in
+    (* Is the interval computed for a variable a singleton? *)
+    let is_singleton =
+      Top.fold ~top:false Cvalue.V.cardinal_zero_or_one
+    in
+    fun exp ->
+      match exp.enode with
+      | Lval lval
+        when Cil.isIntegralOrPointerType (Cil.typeOfLval lval)
+          && not (Eval_typ.lval_contains_volatile lval)
+          && not (is_singleton (eval exp)) ->
+        Some (Variable.make_lval lval, Ival.zero)
+
+      | CastE (typ, { enode = Lval (Var vi, NoOffset) })
+        when Cil.isIntegralType typ
+          && Cil.isFloatingType vi.vtype
+          && not (Cil.typeHasQualifier "volatile" vi.vtype)
+          && not (is_singleton (eval exp)) ->
+        Some (Variable.make_int vi, Ival.zero)
+
+      | StartOf (Var vi, offset) | AddrOf (Var vi, offset) ->
+        let var = Variable.make_startof vi in
+        let* coeff = offset_to_coeff eval vi.vtype offset in
+        Some (var, coeff)
+
+      | _ -> None
+
+
   (* ------------------------------ Lattice --------------------------------- *)
 
   let top =
     { octagons = Octagons.top;
       intervals = Intervals.top;
       relations = Relations.empty;
-      modified = Zone.top; }
+      modified = Zone.top;
+      deps = Deps.empty }
 
   let empty () =
     { octagons = Octagons.top;
       intervals = Intervals.top;
       relations = Relations.empty;
-      modified = Zone.bottom; }
+      modified = Zone.bottom;
+      deps = Deps.empty }
 
   let is_included t1 t2 =
     Octagons.is_included t1.octagons t2.octagons
     && Intervals.is_included t1.intervals t2.intervals
     && Zone.is_included t1.modified t2.modified
+    && Deps.is_included t1.deps t2.deps
 
   let join t1 t2 =
     let octagons =
@@ -906,7 +1379,9 @@ module State = struct
     let state =
       { octagons; relations;
         intervals = Intervals.join t1.intervals t2.intervals;
-        modified = Zone.join t1.modified t2.modified; }
+        modified = Zone.join t1.modified t2.modified;
+        deps = Deps.join t1.deps t2.deps;
+      }
     in
     check "join" state
 
@@ -943,7 +1418,8 @@ module State = struct
     let state =
       { octagons; relations;
         intervals = Intervals.widen t1.intervals t2.intervals;
-        modified = Zone.join t1.modified t2.modified; }
+        modified = Zone.join t1.modified t2.modified;
+        deps = Deps.join t1.deps t2.deps }
     in
     check "widen" state
 
@@ -952,7 +1428,8 @@ module State = struct
     Intervals.narrow t1.intervals t2.intervals >>- fun intervals ->
     let relations = Relations.union t1.relations t2.relations in
     let modified = Zone.narrow t1.modified t2.modified in
-    `Value { octagons; intervals; relations; modified; }
+    let deps = Deps.narrow t1.deps t2.deps in
+    `Value { octagons; intervals; relations; modified; deps }
 
   (* -------------- Transitive closure when adding an octagon --------------- *)
 
@@ -999,7 +1476,7 @@ module State = struct
   let saturate state x y rel1 =
     try
       let y_related = Relations.find y state.relations in
-      let y_related = Variable.Set.remove x y_related in
+      let y_related = VarSet.remove x y_related in
       let aux z state =
         state >>- fun state ->
         try
@@ -1011,10 +1488,11 @@ module State = struct
           add_diamond state pair diamond
         with Not_found -> `Value state
       in
-      Variable.Set.fold aux y_related (`Value state)
+      VarSet.fold aux y_related (`Value state)
     with Not_found -> `Value state
 
-  let add_octagon state octagon =
+  (* Adds dependencies to the state only if [eval_deps] is not None. *)
+  let add_octagon eval_deps state octagon =
     if Ival.(equal top octagon.value) || is_redundant state.intervals octagon
     then `Value state
     else
@@ -1034,32 +1512,45 @@ module State = struct
       state >>- fun state ->
       Octagons.add_octagon octagon state.octagons >>-: fun octagons ->
       let relations = Relations.relate octagon.variables state.relations in
-      { state with octagons; relations }
+      let variable_list = Pair.variable_list octagon.variables in
+      let deps =
+        match eval_deps with
+        | None -> state.deps
+        | Some eval_deps ->
+          let add_var_deps deps v =
+            Deps.add v (eval_deps v) deps
+          in
+          List.fold_left add_var_deps state.deps variable_list
+      in
+      { state with octagons; relations; deps }
 
-  let add_diamond state variables diamond =
-    add_octagon state { variables; operation = Add; value = diamond.add }
+  let add_diamond eval_deps state variables diamond =
+    add_octagon eval_deps state { variables; operation = Add; value = diamond.add }
     >>- fun state ->
-    add_octagon state { variables; operation = Sub; value = diamond.sub }
+    add_octagon eval_deps state { variables; operation = Sub; value = diamond.sub }
 
   let remove state x =
-    let intervals = Intervals.remove x state.intervals in
-    let state = { state with intervals } in
-    try
-      let relations = Relations.find x state.relations in
-      let remove_one y state =
-        try
-          let yrelations = Relations.find y state.relations in
-          let yrelations = Variable.Set.remove x yrelations in
-          let relations = Relations.add y yrelations state.relations in
-          let pair, _ = Pair.make x y in
-          let octagons = Octagons.remove pair state.octagons in
-          { state with octagons; relations }
-        with Not_found -> state
-      in
-      let state = Variable.Set.fold remove_one relations state in
-      let relations = Relations.remove x state.relations in
-      { state with relations }
-    with Not_found -> state
+    match Deps.remove x state.deps with
+    | None -> state
+    | Some deps ->
+      let intervals = Intervals.remove x state.intervals in
+      let state = { state with intervals; deps } in
+      try
+        let relations = Relations.find x state.relations in
+        let remove_one y state =
+          try
+            let yrelations = Relations.find y state.relations in
+            let yrelations = VarSet.remove x yrelations in
+            let relations = Relations.add y yrelations state.relations in
+            let pair, _ = Pair.make x y in
+            let octagons = Octagons.remove pair state.octagons in
+            { state with octagons; relations }
+          with Not_found -> state
+        in
+        let state = VarSet.fold remove_one relations state in
+        let relations = Relations.remove x state.relations in
+        { state with relations }
+      with Not_found -> state
 
   let related_octagons state x =
     try
@@ -1072,7 +1563,7 @@ module State = struct
           (y, diamond) :: acc
         with Not_found -> acc
       in
-      Variable.Set.fold aux related []
+      VarSet.fold aux related []
     with Not_found -> []
 
   (* x' = ±x - delta *)
@@ -1108,9 +1599,10 @@ module State = struct
         { state with octagons }
       with Not_found -> state
     in
-    Variable.Set.fold aux x_related state
+    VarSet.fold aux x_related state
 end
 
+
 (* -------------------------------------------------------------------------- *)
 (*                               Octagon domain                               *)
 (* -------------------------------------------------------------------------- *)
@@ -1126,17 +1618,42 @@ module Domain = struct
 
   let top_value = `Value (Cvalue.V.top, None), Alarmset.all
 
-  let extract_expr ~oracle _context state expr =
-    let evaluate_expr expr =
-      match fst (oracle expr) with
-      | `Bottom -> `Top (* should not happen *)
-      | `Value cvalue ->
-        try `Value (Cvalue.V.project_ival cvalue)
-        with Cvalue.V.Not_based_on_null -> `Top
+  (* Evaluator building. *)
+
+  let evaluator_from_oracle oracle = fun expr ->
+    match fst (oracle expr) with
+    | `Bottom -> `Top (* should not happen *)
+    | `Value (Cvalue.V.Top _) -> `Top
+    | `Value cvalue -> `Value cvalue
+
+  let evaluator_from_valuation valuation =
+    let eval_exp expr =
+      match valuation.Abstract_domain.find expr with
+      | `Top -> `Top
+      | `Value record ->
+        match record.Eval.value.v with
+        | `Bottom -> `Top (* TODO: why this keeps happening? *)
+        | `Value (Cvalue.V.Top _) -> `Top
+        | `Value cvalue -> `Value cvalue
+    in
+    let eval_loc lval =
+      match valuation.Abstract_domain.find_loc lval with
+      | `Top -> Precise_locs.loc_top
+      | `Value record -> record.loc
+    in
+    let eval_deps var =
+      Variable.deps ~eval_loc var
     in
+    eval_exp, eval_deps
+
+  (* Domain functions *)
+
+  let extract_expr ~oracle _context state expr =
+    let eval = evaluator_from_oracle oracle in
     let evaluate_octagon octagon = Octagons.evaluate octagon state.octagons in
+    let env = mk_variable_builder eval state in
     let ival, alarms =
-      Rewriting.evaluate_through_octagons evaluate_expr evaluate_octagon expr
+      Rewriting.evaluate_through_octagons eval evaluate_octagon env expr
     in
     if Ival.(equal ival top)
     then top_value
@@ -1148,11 +1665,11 @@ module Domain = struct
 
   let reduce_further state expr value =
     match expr.enode with
-    | Lval (Var x, NoOffset) when Cil.isIntegralType x.vtype ->
+    | Lval lval when Cil.(isIntegralOrPointerType (typeOfLval lval)) ->
       begin
         try
           let x_ival = Cvalue.V.project_ival value in
-          let var = Variable.make x in
+          let var = Variable.make_lval lval in
           let kind = Variable.kind var in
           let octagons = State.related_octagons state var in
           let reduce acc (y, octagons) =
@@ -1181,58 +1698,44 @@ module Domain = struct
       end
     | _ -> []
 
-
-  let kill_base base state =
-    try
-      let varinfo = Base.to_varinfo base in
-      let vars = Variable.get_all varinfo in
-      List.fold_left State.remove state vars
-    with Base.Not_a_C_variable -> state
-
   let kill zone state =
     if Locations.Zone.(equal zone top)
     then top
     else
       let modified = Locations.Zone.join state.modified zone in
-      let state = Zone.fold_bases kill_base zone state in
+      let vars = Deps.intersects_zone state.deps zone in
+      let state = List.fold_left State.remove state vars in
       { state with modified }
 
-  (* Evaluation function of expressions to ival, from a [valuation]. *)
-  let evaluation_function valuation = fun expr ->
-    match valuation.Abstract_domain.find expr with
-    | `Top -> `Top
-    | `Value record ->
-      match record.Eval.value.v with
-      | `Bottom -> `Top (* TODO: why this keeps happening? *)
-      | `Value cvalue ->
-        try `Value (Cvalue.V.project_ival cvalue)
-        with Cvalue.V.Not_based_on_null -> `Top
 
   exception EBottom
 
-  let infer_octagons evaluate expr ival state =
-    let octagons = Rewriting.make_octagons evaluate expr ival in
+  let infer_octagons valuation expr ival state =
+    let eval_exp, eval_deps = evaluator_from_valuation valuation in
+    let env = mk_variable_builder eval_exp state in
+    let octagons = Rewriting.make_octagons eval_exp env expr ival in
     let add_octagon state octagon =
-      match State.add_octagon state octagon with
+      match State.add_octagon (Some eval_deps) state octagon with
       | `Bottom -> raise EBottom
       | `Value state -> state
     in
     List.fold_left add_octagon state octagons
 
-  let infer_interval expr ival state =
+  let infer_interval eval_deps expr ival state =
     if not infer_intervals
     then state
     else
       match expr.enode with
-      | Lval (Var varinfo, NoOffset)
-        when Cil.isIntegralType varinfo.vtype ->
-        let var = Variable.make varinfo in
+      | Lval lval when Cil.(isIntegralType (typeOfLval lval))
+                    && not (Eval_typ.lval_contains_volatile lval) ->
+        let var = Variable.make_lval lval in
+        let deps = Deps.add var (eval_deps var) state.deps in
         let intervals = Intervals.add var ival state.intervals in
-        { state with intervals }
+        { state with intervals; deps }
       | _ -> state
 
   let update valuation state =
-    let evaluate = evaluation_function valuation in
+    let _eval_exp, eval_deps = evaluator_from_valuation valuation in
     let aux expr record state =
       let value = record.Eval.value in
       match record.reductness, value.v, value.initialized, value.escaping with
@@ -1240,8 +1743,8 @@ module Domain = struct
         begin
           try
             let ival = Cvalue.V.project_ival cvalue in
-            let state = infer_octagons evaluate expr ival state in
-            infer_interval expr ival state
+            let state = infer_octagons valuation expr ival state in
+            infer_interval eval_deps expr ival state
           with Cvalue.V.Not_based_on_null -> state
         end
       | _ -> state
@@ -1249,7 +1752,7 @@ module Domain = struct
     try `Value (check "update" (valuation.Abstract_domain.fold aux state))
     with EBottom -> `Bottom
 
-  let assign_interval variable assigned state =
+  let assign_interval eval_deps variable assigned state =
     if not infer_intervals
     then state
     else
@@ -1260,17 +1763,27 @@ module Domain = struct
           try
             let ival = Cvalue.V.project_ival v in
             let intervals = Intervals.add variable ival state.intervals in
-            { state with intervals }
+            let deps = Deps.add variable (eval_deps variable) state.deps in
+            { state with intervals; deps }
           with Cvalue.V.Not_based_on_null -> state
         end
       | _ -> state
 
-  (* Assigns integer [varinfo] to [expr]. *)
-  let assign_variable varinfo expr assigned valuation state =
-    let evaluate = evaluation_function valuation in
+  (* Assigns [lvalue] to [expr]. *)
+  let assign_variable lvalue expr assigned valuation state =
+    let eval_exp, eval_deps = evaluator_from_valuation valuation in
+    let variable = Variable.make_lval lvalue in
+    (* Remove lvals refering to the variable *)
+    let lvalue_zone = (eval_deps variable).data in
+    let modified = Locations.Zone.join state.modified lvalue_zone in
+    let state = { state with modified } in
+    let vars = Deps.intersects_zone state.deps lvalue_zone in
+    let vars = List.filter (Fun.negate (Variable.equal variable)) vars in
+    let state = List.fold_left State.remove state vars in
+    (* Interpret inversible assignment if possible *)
     (* TODO: redundant with rewrite_binop below. *)
-    let vars = Rewriting.rewrite evaluate expr in
-    let variable = Variable.make varinfo in
+    let env = mk_variable_builder eval_exp state in
+    let vars = Rewriting.rewrite eval_exp env expr in
     let equal_varinfo v = Variable.equal variable v.Rewriting.var in
     let state =
       try
@@ -1279,26 +1792,27 @@ module Domain = struct
         State.sub_delta ~inverse state variable var.Rewriting.coeff
       with Not_found -> State.remove state variable
     in
-    let state = assign_interval variable assigned state in
-    let enode = Lval (Var varinfo, NoOffset) in
+    let state = assign_interval eval_deps variable assigned state in
+    let enode = Lval lvalue in
     let left_expr = Cil.new_exp ~loc:expr.eloc enode in
     (* On the assignment X = E; if X-E can be rewritten as ±(X±Y-v),
        then the octagonal constraint [X±Y ∈ v] holds. *)
-    let octagons = Rewriting.rewrite_binop evaluate left_expr Sub expr in
+    let octagons = Rewriting.rewrite_binop eval_exp env left_expr Sub expr in
     let state =
       List.fold_left
         (fun acc (_sign, octagon) ->
-           acc >>- fun state -> State.add_octagon state octagon)
+           acc >>- fun state ->
+           State.add_octagon (Some eval_deps) state octagon)
         (`Value state) octagons
     in
     state >>-: check "precise assign"
 
-  let assign _kinstr left_value expr assigned valuation state =
-    update valuation state >>- fun state ->
-    match left_value.lval with
-    | Var varinfo, NoOffset when Cil.isIntegralType varinfo.vtype ->
-      assign_variable varinfo expr assigned valuation state
-    | _ ->
+  let assign kinstr left_value expr assigned valuation state =
+    if kinstr <> Kglobal
+    && Cil.isIntegralOrPointerType left_value.ltyp
+    && not (Eval_typ.lval_contains_volatile left_value.lval)
+    then assign_variable left_value.lval expr assigned valuation state
+    else
       let written_loc = Precise_locs.imprecise_location left_value.lloc in
       let written_zone =
         Locations.(enumerate_valid_bits Write written_loc)
@@ -1310,7 +1824,8 @@ module Domain = struct
 
   let start_recursive_call recursion state =
     let vars = List.map fst recursion.substitution @ recursion.withdrawal in
-    let vars = List.flatten (List.map Variable.get_all vars) in
+    let var_deps v = Deps.intersects_var state.deps v in
+    let vars = List.flatten (List.map var_deps vars) in
     List.fold_left State.remove state vars
 
   let start_call _stmt call recursion valuation state =
@@ -1327,8 +1842,9 @@ module Domain = struct
         `Value (start_recursive_call recursion state)
       | None ->
         let assign_formal state { formal; concrete; avalue } =
-          if Cil.isIntegralType formal.vtype
-          then state >>- assign_variable formal concrete avalue valuation
+          let lval = (Var formal, NoOffset) in
+          if Cil.isIntegralOrPointerType formal.vtype
+          then state >>- assign_variable lval concrete avalue valuation
           else state
         in
         List.fold_left assign_formal (`Value state) call.arguments
@@ -1348,7 +1864,8 @@ module Domain = struct
 
   let enter_scope _kind _varinfos state = state
   let leave_scope _kf varinfos state =
-    let vars = List.flatten (List.map Variable.get_all varinfos) in
+    let var_deps v = Deps.intersects_var state.deps v in
+    let vars = List.concat_map var_deps varinfos in
     let state = List.fold_left State.remove state vars in
     check "leave_scope" state
 
@@ -1360,34 +1877,33 @@ module Domain = struct
     then Base.SetLattice.empty
     else
       let add_related_bases acc var =
-        let related = Relations.find var state.relations in
-        Variable.Set.fold
-          (fun var -> Base.Hptset.add (Variable.base var))
-          related acc
+        try
+          let related = Relations.find var state.relations in
+          VarSet.elements related |>
+          List.map (Deps.get_var_bases state.deps) |>
+          List.fold_left Base.SetLattice.join acc
+        with Not_found -> acc
       in
       let aux base acc =
-        try
-          let varinfo = Base.to_varinfo base in
-          let variables = Variable.get_all varinfo in
-          List.fold_left add_related_bases acc variables
-        with Base.Not_a_C_variable | Not_found -> acc
+        let variables = Deps.intersects_base state.deps base in
+        List.fold_left add_related_bases acc variables
       in
-      let hptset = Base.Hptset.fold aux bases Base.Hptset.empty in
-      Base.SetLattice.inject hptset
+      Base.Hptset.fold aux bases Base.SetLattice.empty
 
   let filter _kind bases state =
     if intraprocedural ()
     then state
     else
-      let mem_var var = Base.Hptset.mem (Variable.base var) bases in
+      let removed_vars, deps = Deps.filter bases state.deps in
+      let mem_var v = not (VarSet.mem v removed_vars) in
       let mem_pair pair =
         let x, y = Pair.get pair in
         mem_var x && mem_var y
       in
       let octagons = Octagons.filter mem_pair state.octagons in
-      let intervals = Intervals.filter mem_var state.intervals in
-      let relations = Relations.filter mem_var state.relations in
-      { state with octagons; intervals; relations; }
+      let intervals = Intervals.diff_with_shape removed_vars state.intervals in
+      let relations = Relations.diff_with_shape removed_vars state.relations in
+      { state with octagons; intervals; relations; deps }
 
   let interprocedural_reuse =
     let cache = Hptmap_sig.PersistentCache "Octagons.reuse"
@@ -1399,6 +1915,8 @@ module Domain = struct
     and join_rel = Relations.union in
     fun kf ~current_input ~previous_output ->
       let current_input = kill previous_output.modified current_input in
+      let intervals = join_itv previous_output.intervals current_input.intervals
+      and deps = Deps.narrow previous_output.deps current_input.deps in
       (* We use [add_diamond] to add each relation from the previous output
          into the current input, in order to benefit from the (partial)
          saturation of octagons performed by this function. For a maximum
@@ -1407,12 +1925,9 @@ module Domain = struct
          of the maps from the previous output and the current input. *)
       if saturate_octagons
       then
-        let intervals =
-          join_itv previous_output.intervals current_input.intervals
-        in
-        let state = { current_input with intervals } in
+        let state = { current_input with intervals; deps } in
         let add_diamond variables diamond acc =
-          match add_diamond acc variables diamond with
+          match add_diamond None acc variables diamond with
           | `Value state -> state
           | `Bottom ->
             Self.failure ~current:true ~once:true
@@ -1425,9 +1940,9 @@ module Domain = struct
         Octagons.fold add_diamond previous_output.octagons state
       else
         { octagons = join_oct previous_output.octagons current_input.octagons;
-          intervals = join_itv previous_output.intervals current_input.intervals;
           relations = join_rel previous_output.relations current_input.relations;
-          modified = current_input.modified }
+          modified = current_input.modified;
+          intervals; deps; }
 
   let reuse kf _bases ~current_input ~previous_output =
     if intraprocedural ()
@@ -1435,9 +1950,6 @@ module Domain = struct
     else
       let t = interprocedural_reuse kf ~current_input ~previous_output in
       check "reuse result" t
-
-
-
 end
 
 include Domain
diff --git a/src/plugins/eva/engine/compute_functions.ml b/src/plugins/eva/engine/compute_functions.ml
index cfb195799f725002717bd4354080abf90cfa08fd..5e913a57d2c6738e82bcb20c861fa11a0cbc8177 100644
--- a/src/plugins/eva/engine/compute_functions.ml
+++ b/src/plugins/eva/engine/compute_functions.ml
@@ -85,6 +85,7 @@ let pre_analysis () =
   Widen.precompute_widen_hints ();
   Builtins.prepare_builtins ();
   Eva_perf.reset ();
+  Statistics.reset_all ();
   (* We may be resuming Value from a previously crashed analysis. Clear
      degeneration states *)
   Eva_utils.DegenerationPoints.clear ();
@@ -363,6 +364,7 @@ module Make (Abstract: Abstractions.Eva) = struct
       post_analysis ();
       Abstract.Dom.post_analysis final_state;
       Summary.print_summary ();
+      Statistics.export_as_csv ();
       restore_signals ()
     in
     let cleanup () =
diff --git a/src/plugins/eva/engine/iterator.ml b/src/plugins/eva/engine/iterator.ml
index c05c4a2f10b16094f37ca59e57c63161cf4f5389..2a0c7af021ac216b6eae8cea7f8315e3604f3ece 100644
--- a/src/plugins/eva/engine/iterator.ml
+++ b/src/plugins/eva/engine/iterator.ml
@@ -36,6 +36,7 @@ let check_signals, signal_abort =
 
 let dkey = Self.dkey_iterator
 let dkey_callbacks = Self.dkey_callbacks
+let stat_iterations = Statistics.register_statement_stat "iterations"
 
 let blocks_share_locals b1 b2 =
   match b1.blocals, b2.blocals with
@@ -463,7 +464,7 @@ module Make_Dataflow
     end;
     (* Get vertex store *)
     let store = get_vertex_store v in
-    (* Join incoming s tates *)
+    (* Join incoming states *)
     let flow = Partitioning.join sources store in
     let flow =
       match v.vertex_start_of with
@@ -562,6 +563,7 @@ module Make_Dataflow
         not (process_vertex ~widening:true v) || !iteration_count = 0
       do
         Self.debug ~dkey "iteration %d" !iteration_count;
+        Option.iter (Statistics.incr stat_iterations) v.vertex_start_of;
         iterate_list w;
         incr iteration_count;
       done;
diff --git a/src/plugins/eva/engine/mem_exec.ml b/src/plugins/eva/engine/mem_exec.ml
index 71a68968d66278547885435ca8aae20ffc1e569b..a4a530a9741beeddfabb84ce64c3b793ee629878 100644
--- a/src/plugins/eva/engine/mem_exec.ml
+++ b/src/plugins/eva/engine/mem_exec.ml
@@ -20,6 +20,8 @@
 (*                                                                        *)
 (**************************************************************************)
 
+let stat_hits = Statistics.register_function_stat "memexec-hits"
+let stat_misses = Statistics.register_function_stat "memexec-misses"
 
 module SaveCounter =
   State_builder.SharedCounter(struct let name = "Mem_exec.save_counter" end)
@@ -263,10 +265,14 @@ module Make
       let args = List.map (function `Bottom -> None | `Value v -> Some v) args in
       let previous = ActualArgs.Map.find args previous_kf in
       find_match_in_previous kf previous state;
+      Statistics.incr stat_misses kf;
       None
     with
-    | Not_found -> None
+    | Not_found ->
+      Statistics.incr stat_misses kf;
+      None
     | Result_found (outputs, i) ->
+      Statistics.incr stat_hits kf;
       let call_result = outputs in
       Some (call_result, i)
 
diff --git a/src/plugins/eva/engine/transfer_stmt.ml b/src/plugins/eva/engine/transfer_stmt.ml
index 40d9b76071d483c8e5be05e37b31888150a2afa0..71042b2b2e41baab8d8f7d0c49e811f686231910 100644
--- a/src/plugins/eva/engine/transfer_stmt.ml
+++ b/src/plugins/eva/engine/transfer_stmt.ml
@@ -731,7 +731,6 @@ module Make (Abstract: Abstractions.Eva) = struct
     let stack_with_call = (kf, ki_call) :: Eva_utils.call_stack () in
     let cvalue_state = Domain.get_cvalue_or_top state in
     Db.Value.Call_Value_Callbacks.apply (cvalue_state, stack_with_call);
-    Db.Value.merge_initial_state (Eva_utils.call_stack ()) cvalue_state;
     let kind = `Builtin None in
     Cvalue_callbacks.apply_call_hooks stack_with_call kf kind cvalue_state
 
diff --git a/src/plugins/eva/legacy/eval_op.ml b/src/plugins/eva/legacy/eval_op.ml
index 211afbcf983aea4a31991cd1fd39d420d7835b7a..aa9227c45553d7d538902228d7a64968d56395e2 100644
--- a/src/plugins/eva/legacy/eval_op.ml
+++ b/src/plugins/eva/legacy/eval_op.ml
@@ -201,7 +201,7 @@ let pretty_offsetmap typ fmt offsm =
   then Format.fprintf fmt "%s" (Unicode.emptyset_string ())
   else begin
     match Cvalue.V_Offsetmap.single_interval_value offsm with
-    | Some value -> Cvalue.V_Or_Uninitialized.pretty fmt value;
+    | Some value -> Cvalue.V_Or_Uninitialized.pretty_typ (Some typ) fmt value;
     | None ->
       Cvalue.V_Offsetmap.pretty_generic ~typ () fmt offsm;
       pretty_stitched_offsetmap fmt typ offsm
diff --git a/src/plugins/eva/parameters.ml b/src/plugins/eva/parameters.ml
index a8a1b273ecc4111d11114502ac711dbd8902ef92..dca2f98df5726fbd57b4aacb43f2e598e21ace42 100644
--- a/src/plugins/eva/parameters.ml
+++ b/src/plugins/eva/parameters.ml
@@ -1091,6 +1091,18 @@ module NumerorsLogFile =
                   function in the given file"
     end)
 
+let () = Parameter_customize.set_group messages
+module StatisticsFile =
+  Filepath
+    (struct
+      let option_name = "-eva-statistics-file"
+      let arg_name = "file.csv"
+      let file_kind = "CSV"
+      let existence = Fc_Filepath.Indifferent
+      let help = "Dump some internal statistics about the analysis"
+    end)
+
+
 (* ------------------------------------------------------------------------- *)
 (* --- Interpreter mode                                                  --- *)
 (* ------------------------------------------------------------------------- *)
diff --git a/src/plugins/eva/parameters.mli b/src/plugins/eva/parameters.mli
index 4d8288faaa60f03efafc777f3859fa4e41fea8f5..61daa88642517dc801a2a65b73d7b82e80ce6210 100644
--- a/src/plugins/eva/parameters.mli
+++ b/src/plugins/eva/parameters.mli
@@ -125,6 +125,7 @@ module ShowSlevel: Parameter_sig.Int
 module PrintCallstacks: Parameter_sig.Bool
 module ReportRedStatuses: Parameter_sig.Filepath
 module NumerorsLogFile: Parameter_sig.Filepath
+module StatisticsFile: Parameter_sig.Filepath
 
 module MemExecAll: Parameter_sig.Bool
 
diff --git a/src/plugins/eva/partitioning/partition.ml b/src/plugins/eva/partitioning/partition.ml
index f0b7663f535570ad0678aa5c6f3f4617de67430c..14723800087101c1b1049d3fd7a0b910ff631278 100644
--- a/src/plugins/eva/partitioning/partition.ml
+++ b/src/plugins/eva/partitioning/partition.ml
@@ -655,8 +655,8 @@ struct
     in
     List.fold_left transfer [] p
 
-  let iter (f : state -> unit) (p : t) : unit =
-    List.iter (fun (_k,x) -> f x) p
+  let iter (f : key -> state -> unit) (p : t) : unit =
+    List.iter (fun (k, x) -> f k x) p
 
   let join_duplicate_keys (p : t) : t =
     let cmp (k, _) (k', _) = Key.compare k k' in
diff --git a/src/plugins/eva/partitioning/partition.mli b/src/plugins/eva/partitioning/partition.mli
index e1f6d42ab427ffc10fd192ba905db7fb1737731d..caf4e08c2487c27dba54be9916b43945669c14d4 100644
--- a/src/plugins/eva/partitioning/partition.mli
+++ b/src/plugins/eva/partitioning/partition.mli
@@ -195,7 +195,7 @@ sig
   val transfer : ((key * state) -> (key * state) list) -> t -> t
   val transfer_keys : t -> action -> t
 
-  val iter : (state -> unit) -> t -> unit
+  val iter : (key -> state -> unit) -> t -> unit
   val filter_map: (key -> state -> state option) -> t -> t
 
   val join_duplicate_keys: t -> t
diff --git a/src/plugins/eva/partitioning/partitioning_index.ml b/src/plugins/eva/partitioning/partitioning_index.ml
index 8379820d3bff92866607ee46d8f34b1065d6541d..422d29c424b36cfd050c73f464ae880d6c6cbf62 100644
--- a/src/plugins/eva/partitioning/partitioning_index.ml
+++ b/src/plugins/eva/partitioning/partitioning_index.ml
@@ -20,6 +20,10 @@
 (*                                                                        *)
 (**************************************************************************)
 
+let stat_hits = Statistics.register_global_stat "partitioning-index-hits"
+let stat_misses = Statistics.register_global_stat "partitioning-index-misses"
+
+
 (** Partition of the abstract states, computed for each node by the
     dataflow analysis. *)
 module Make (Domain : Abstract.Domain.External)
@@ -86,6 +90,11 @@ module Make (Domain : Abstract.Domain.External)
         then false
         else (Index.add states prefix state; true)
 
+  let add state partition =
+    let r = add state partition in
+    Statistics.incr (if r then stat_misses else stat_hits) ();
+    r
+
   let iter f { states; others } =
     Index.iter (fun _k v -> f v) states;
     List.iter f others
diff --git a/src/plugins/eva/partitioning/partitioning_parameters.ml b/src/plugins/eva/partitioning/partitioning_parameters.ml
index f2ecaebbb2c88b0fa3e27a5e530fabc22e51d95f..bbea9b87aed55ef78df676d4cb53fb1d5ffdaa4e 100644
--- a/src/plugins/eva/partitioning/partitioning_parameters.ml
+++ b/src/plugins/eva/partitioning/partitioning_parameters.ml
@@ -109,7 +109,7 @@ struct
   let universal_splits =
     let add name l =
       try
-        let vi = Globals.Vars.find_from_astinfo name VGlobal in
+        let vi = Globals.Vars.find_from_astinfo name Global in
         let monitor = Partition.new_monitor ~split_limit in
         let expr = Partition.Expression (Cil.evar vi) in
         Partition.Split (expr, Partition.Dynamic, monitor) :: l
diff --git a/src/plugins/eva/partitioning/trace_partitioning.ml b/src/plugins/eva/partitioning/trace_partitioning.ml
index ea47c4aa9a23114915f126f9062413b27b10fc41..2e38c548ff027ad0587432d265d6e0beaff02f6a 100644
--- a/src/plugins/eva/partitioning/trace_partitioning.ml
+++ b/src/plugins/eva/partitioning/trace_partitioning.ml
@@ -23,6 +23,8 @@
 open Cil_types
 open Partition
 
+let stat_max_widenings = Statistics.register_statement_stat "max-widenings"
+
 module Make
     (Abstract: Abstractions.Eva)
     (Kf : sig val kf: kernel_function end) =
@@ -40,8 +42,8 @@ struct
   type state = Domain.t
 
   type store = {
-    rationing: Partition.rationing; (* slevel rationing at this point *)
     flow_actions : action list; (* partitioning actions to be applied *)
+    rationing: bool; (* Is there a slevel rationing in above actions? *)
     store_stmt : stmt option;
     store_index : Index.t; (* Index of all states stored: used to quickly remove
                               new states that have already been propagated. *)
@@ -59,6 +61,7 @@ struct
     mutable widened_state : state option;
     mutable previous_state : state;
     mutable widening_counter : int;
+    mutable widening_steps : int; (* count the number of successive widenings *)
   }
 
   type widening = {
@@ -69,13 +72,27 @@ struct
   (* Constructors *)
 
   let empty_store ~(stmt : stmt option) : store =
-    let limit, merge, flow_actions = match stmt with
-      | None -> max_int, false, []
-      | Some stmt -> slevel stmt, merge stmt, flow_actions stmt
+    let rationing_parameters, flow_actions = match stmt with
+      | None -> None, []
+      | Some stmt ->
+        let flow_actions = flow_actions stmt in
+        (* A skip statement is created on each split annotation: do not ration
+           states on them to avoid meddling in successive split directives. *)
+        if Cil.is_skip stmt.skind && flow_actions <> []
+        then None, flow_actions
+        else Some (slevel stmt, merge stmt), flow_actions
+    in
+    let rationing =
+      match rationing_parameters with
+      | None -> Partition.new_rationing ~limit:max_int ~merge:false
+      | Some (limit, merge) -> Partition.new_rationing ~limit ~merge
+    in
+    let flow_actions =
+      (Ration rationing) :: Update_dynamic_splits :: flow_actions
     in
-    let rationing = Partition.new_rationing ~limit ~merge in
     {
-      rationing; flow_actions;
+      flow_actions;
+      rationing = rationing_parameters <> None;
       store_stmt = stmt;
       store_index = Index.empty ();
       store_partition = Partition.empty;
@@ -106,7 +123,7 @@ struct
     Partition.iter (fun _key state -> Domain.pretty fmt state) s.store_partition
 
   let pretty_flow (fmt : Format.formatter) (flow : flow) =
-    Flow.iter (Domain.pretty fmt) flow
+    Flow.iter (fun _ -> Domain.pretty fmt) flow
 
 
   (* Accessors *)
@@ -258,50 +275,49 @@ struct
     let flow_states =
       List.fold_left Flow.union Flow.empty sources_states
     in
-    (* Handle ration stamps *)
-    dest.incoming_states <- dest.incoming_states + Flow.size flow_states;
-    let rationing_action = Ration dest.rationing in
-    (* Handle Split / Merge operations *)
-    let flow_actions = Update_dynamic_splits :: dest.flow_actions in
     (* Execute actions *)
-    let actions = rationing_action :: flow_actions in
     let flow_states =
-      List.fold_left Flow.transfer_keys flow_states actions
+      List.fold_left Flow.transfer_keys flow_states dest.flow_actions
     in
-    (* Add states to the store but filter out already propagated states *)
-    let update key current_state =
-      (* Inclusion test *)
-      let state =
-        try
-          let previous_state = Partition.find key dest.store_partition in
-          if Domain.is_included current_state previous_state then
-            (* The current state is included in the previous; stop *)
-            None
-          else begin
-            (* Propagate the join of the two states *)
-            if is_loop_head then
-              Self.feedback ~level:1 ~once:true ~current:true
-                "starting to merge loop iterations";
-            Some (Domain.join previous_state current_state)
-          end
-        with
-        (* There is no previous state, propagate normally *)
-          Not_found -> Some current_state
-      in
-      (* Add the propagated state to the store *)
-      let add s =
-        dest.store_partition <- Partition.replace key s dest.store_partition;
-      in
-      Option.iter add state;
-      (* Filter out already propagated states (only at statements). *)
-      if dest.store_stmt = None
-      then state
-      else Extlib.opt_filter (fun s -> Index.add s dest.store_index) state
+    (* Add the propagated state to the store *)
+    let add_state key s =
+      dest.store_partition <- Partition.replace key s dest.store_partition;
     in
-    let flow = Flow.join_duplicate_keys flow_states in
-    let flow = Flow.filter_map update flow in
-    Option.iter (partitioning_feedback dest flow) dest.store_stmt;
-    flow
+    if not (dest.rationing) then begin
+      Flow.iter add_state flow_states;
+      flow_states
+    end else begin
+      (* Handle ration stamps *)
+      dest.incoming_states <- dest.incoming_states + Flow.size flow_states;
+      (* Add states to the store but filter out already propagated states *)
+      let update key current_state =
+        (* Inclusion test *)
+        let state =
+          try
+            let previous_state = Partition.find key dest.store_partition in
+            if Domain.is_included current_state previous_state then
+              (* The current state is included in the previous; stop *)
+              None
+            else begin
+              (* Propagate the join of the two states *)
+              if is_loop_head then
+                Self.feedback ~level:1 ~once:true ~current:true
+                  "starting to merge loop iterations";
+              Some (Domain.join previous_state current_state)
+            end
+          with
+          (* There is no previous state, propagate normally *)
+            Not_found -> Some current_state
+        in
+        Option.iter (add_state key) state;
+        (* Filter out already propagated states. *)
+        Extlib.opt_filter (fun s -> Index.add s dest.store_index) state
+      in
+      let flow = Flow.join_duplicate_keys flow_states in
+      let flow = Flow.filter_map update flow in
+      Option.iter (partitioning_feedback dest flow) dest.store_stmt;
+      flow
+    end
 
   let widen (w : widening) (flow : flow) : flow =
     let stmt = w.widening_stmt in
@@ -336,6 +352,8 @@ struct
           w.previous_state <- next;
           w.widened_state <- Some next;
           w.widening_counter <- widening_period - 1;
+          w.widening_steps <- w.widening_steps + 1;
+          Statistics.grow stat_max_widenings stmt w.widening_steps;
           Some next
         end
       with Not_found ->
@@ -345,7 +363,9 @@ struct
           let ws =
             { widened_state = None;
               previous_state = curr;
-              widening_counter = widening_delay - 1; }
+              widening_counter = widening_delay - 1;
+              widening_steps = 0
+            }
           in
           w.widening_partition <- Partition.replace key ws w.widening_partition
         end;
diff --git a/src/plugins/eva/utils/eva_annotations.ml b/src/plugins/eva/utils/eva_annotations.ml
index dc8a7b04de93c3339b11c2a6491735cc636c6c9f..8a626416fecf5ab947f5dd52142218fb32d3b535 100644
--- a/src/plugins/eva/utils/eva_annotations.ml
+++ b/src/plugins/eva/utils/eva_annotations.ml
@@ -62,12 +62,18 @@ type allocation_kind = By_stack | Fresh | Fresh_weak | Imprecise
 
 exception Parse_error
 
+(* Where an Eva directive is applied. *)
+type kind =
+  | Here (* The directive is applied when encountered. *)
+  | Stmt (* The directive has effect on the next statement. *)
+  | Loop (* The directive concerns a loop. *)
+
 module type Annotation =
 sig
   type t
 
   val name : string
-  val is_loop_annot : bool
+  val kind : kind
   val parse : typing_context:Logic_typing.typing_context -> lexpr list -> t
   val export : t -> acsl_extension_kind
   val import : acsl_extension_kind -> t
@@ -87,16 +93,19 @@ struct
     print fmt (import lp)
 
   let () =
-    if is_loop_annot then
-      Acsl_extension.register_code_annot_next_loop name typer ~printer false
-    else
-      Acsl_extension.register_code_annot_next_stmt name typer ~printer false
+    let register =
+      match kind with
+      | Here -> Acsl_extension.register_code_annot
+      | Stmt -> Acsl_extension.register_code_annot_next_stmt
+      | Loop -> Acsl_extension.register_code_annot_next_loop
+    in
+    register name typer ~printer false
 
   let get stmt =
     let filter_add _emitter annot acc =
       match annot.annot_content with
-      | Cil_types.AExtended (_, is_loop_annot', {ext_name=name'; ext_kind})
-        when name' = name && is_loop_annot' = is_loop_annot ->
+      | Cil_types.AExtended (_, is_loop_annot, {ext_name=name'; ext_kind})
+        when name' = name && is_loop_annot = (kind = Loop) ->
         import ext_kind :: acc
       | _ -> acc
     in
@@ -106,7 +115,7 @@ struct
     let loc = Cil_datatype.Stmt.loc stmt in
     let param = M.export annot in
     let extension = Logic_const.new_acsl_extension name loc false param in
-    let annot_node = Cil_types.AExtended ([], is_loop_annot, extension) in
+    let annot_node = Cil_types.AExtended ([], kind = Loop, extension) in
     let code_annotation = Logic_const.new_code_annotation annot_node in
     Annotations.add_code_annot emitter stmt code_annotation
 end
@@ -116,7 +125,7 @@ module Slevel = Register (struct
     type t = slevel_annotation
 
     let name = "slevel"
-    let is_loop_annot = false
+    let kind = Here
 
     let parse ~typing_context:_ = function
       | [{lexpr_node = PLvar "default"}] -> SlevelDefault
@@ -161,7 +170,7 @@ module Unroll = Register (struct
     type t = unroll_annotation
 
     let name = "unroll"
-    let is_loop_annot = true
+    let kind = Loop
 
     let parse ~typing_context = function
       | [] -> UnrollFull
@@ -191,6 +200,8 @@ struct
      when possible, to avoid changes due to its reconversion to a C term. *)
   type t = split_term * Cil_types.term option
 
+  let kind = Here
+
   let term_to_exp = Logic_to_c.term_to_exp ?result:None
 
   let parse ~typing_context:context = function
@@ -231,19 +242,16 @@ end
 module Split = Register (struct
     include SplitTermAnnotation
     let name = "split"
-    let is_loop_annot = false
   end)
 
 module Merge = Register (struct
     include SplitTermAnnotation
     let name = "merge"
-    let is_loop_annot = false
   end)
 
 module DynamicSplit = Register (struct
     include SplitTermAnnotation
     let name = "dynamic_split"
-    let is_loop_annot = false
   end)
 
 let get_slevel_annot stmt =
@@ -275,7 +283,7 @@ let add_flow_annot ~emitter stmt flow_annotation =
 module Subdivision = Register (struct
     type t = int
     let name = "subdivide"
-    let is_loop_annot = false
+    let kind = Stmt
 
     let parse ~typing_context:_ = function
       | [{lexpr_node = PLconstant (IntConstant i)}] ->
@@ -316,7 +324,7 @@ module Allocation = struct
   include Register (struct
       type t = allocation_kind
       let name = "eva_allocate"
-      let is_loop_annot = false
+      let kind = Stmt
 
       let parse ~typing_context:_ = function
         | [{lexpr_node = PLvar s}] -> Extlib.the ~exn:Parse_error (of_string s)
@@ -356,7 +364,7 @@ let get_allocation = Allocation.get
 module ArraySegmentation = Register (struct
     type t = Cil_types.varinfo * Cil_types.offset * Cil_types.exp list
     let name = "array_partition"
-    let is_loop_annot = false
+    let kind = Here
 
     let convert = function
       | {term_node =  TLval (TVar {lv_origin=Some vi}, toffset)} :: tbounds ->
@@ -402,7 +410,7 @@ let read_array_segmentation ext = ArraySegmentation.import ext.ext_kind
 module DomainScope = Register (struct
     type t = string * Cil_types.varinfo list
     let name = "eva_domain_scope"
-    let is_loop_annot = false
+    let kind = Here
 
     let parse ~typing_context:context =
       let parse_domain = function
diff --git a/src/plugins/eva/utils/eva_utils.ml b/src/plugins/eva/utils/eva_utils.ml
index 75d902623d8bce4deb8a0a2bcc8eb28181a5b2c8..7dbc948a1e05968b67aeee3d0ae3c17ccae81c3e 100644
--- a/src/plugins/eva/utils/eva_utils.ml
+++ b/src/plugins/eva/utils/eva_utils.ml
@@ -138,6 +138,11 @@ let create_new_var name typ =
 
 let is_const_write_invalid typ = Cil.typeHasQualifier "const" typ
 
+let find_return_var kf =
+  match (Kernel_function.find_return kf).skind with
+  | Return (Some ({enode = Lval ((Var vi, NoOffset))}), _) -> Some vi
+  | _ | exception Kernel_function.No_Statement -> None
+
 (* Find if a postcondition contains [\result] *)
 class postconditions_mention_result = object
   inherit Visitor.frama_c_inplace
diff --git a/src/plugins/eva/utils/eva_utils.mli b/src/plugins/eva/utils/eva_utils.mli
index 0903cdabad18fdaa60b3c33e59be36f1a4e93f8a..e02e47c866017db14b252a76791b8f7cf046af87 100644
--- a/src/plugins/eva/utils/eva_utils.mli
+++ b/src/plugins/eva/utils/eva_utils.mli
@@ -72,6 +72,10 @@ val is_const_write_invalid: typ -> bool
 (** Detect that the type is const, and that option [-global-const] is set. In
     this case, we forbid writing in a l-value that has this type. *)
 
+val find_return_var: kernel_function -> varinfo option
+(** Returns the varinfo returned by the given function.
+    Returns None if the function returns void or has no return statement. *)
+
 val postconditions_mention_result: Cil_types.funspec -> bool
 (** Does the post-conditions of this specification mention [\result]? *)
 
@@ -118,6 +122,10 @@ val deps_of_expr:
 (** Given a function computing the location of lvalues, computes the memory
     dependencies of an expression. *)
 
+val deps_of_lval: (lval -> Precise_locs.precise_location) -> lval -> deps
+(** Given a function computing the location of lvalues, computes the memory
+    dependencies of an lvalue. *)
+
 (** Computes the height of an expression, that is the maximum number of nested
     operations in this expression. *)
 val height_expr: exp -> int
diff --git a/src/plugins/eva/utils/statistics.ml b/src/plugins/eva/utils/statistics.ml
new file mode 100644
index 0000000000000000000000000000000000000000..508a68db4ad07966275613466a6fd24c6ce5b10a
--- /dev/null
+++ b/src/plugins/eva/utils/statistics.ml
@@ -0,0 +1,212 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2023                                               *)
+(*    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).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+(* Statistics are stored in a dictionary, implemented as an hashtable from
+   keys to integers.
+
+   [Key] is the representation of the dictionary keys: a couple of a registered
+   statistic (type ['a t]) accompanied by the function or the statement the stat
+   is about (type ['a]).
+
+   Statistics must be registered before usage. The registry keeps track of the
+   registered statistics and allow the reloading of projects by matching the
+   previous stats to the current ones.
+*)
+
+(* --- Type --- *)
+
+type _ kind =
+  | Global : unit kind
+  | Function : Cil_types.kernel_function kind
+  | Statement : Cil_types.stmt kind
+
+type 'a t = {
+  id: int;
+  name: string;
+  kind: 'a kind;
+}
+
+
+(* --- Registry --- *)
+
+type registered_stat = Registered : 'a t -> registered_stat [@@unboxed]
+
+let kind_to_string : type a. a kind -> string = function
+  | Global -> "global"
+  | Function  -> "function"
+  | Statement -> "statement"
+
+let registry = Hashtbl.create 13
+let last_id = ref 0
+
+let register (type a) (name : string) (kind : a kind) : a t =
+  try
+    (* If the stat is already registered, return the previous one *)
+    let Registered stat = Hashtbl.find registry name in
+    match stat.kind, kind with (* equality must be ensured to return the right type of stat *)
+    | Global, Global -> stat
+    | Function, Function -> stat
+    | Statement, Statement -> stat
+    | _ ->
+      Self.fatal
+        "%s statistic \"%s\" was already registered with as a %s statistic"
+        name (kind_to_string kind) (kind_to_string stat.kind)
+  with Not_found ->
+    (* Otherwise, create a new record for the stat *)
+    incr last_id;
+    let stat = { id = !last_id; name; kind } in
+    Hashtbl.add registry name (Registered stat);
+    stat
+
+let register_global_stat name =
+  register name Global
+
+let register_function_stat name =
+  register name Function
+
+let register_statement_stat name =
+  register name Statement
+
+
+(* --- Keys --- *)
+
+type key = Key : 'a t * 'a -> key
+
+module Key_Datatype = struct
+  include Datatype.Serializable_undefined
+
+  type t = key
+  let name = "Statistics.Key"
+  let rehash (Key (s, x)) =
+    (Key (register s.name s.kind, x))
+  let reprs = [Key ({ id = 0; name="dummy"; kind=Global }, ())]
+  let equal = Datatype.from_compare
+  let compare (Key (s1,x1)) (Key (s2,x2)) =
+    let c = s1.id - s2.id in
+    if c <> 0 then c else
+      match s1.kind, s2.kind with
+      | Global, Global -> 0
+      | Function, Function -> Kernel_function.compare x1 x2
+      | Statement, Statement -> Cil_datatype.Stmt.compare x1 x2
+      | Global, (Function | Statement) -> -1
+      | (Function | Statement), Global -> 1
+      | Function, Statement -> -1
+      | Statement, Function -> 1
+  let hash (Key (s,x)) =
+    let h = match s.kind with
+      | Global -> 0
+      | Function -> Kernel_function.hash x
+      | Statement -> Cil_datatype.Stmt.hash x
+    in
+    Hashtbl.hash (s.id, h)
+  let copy k = k
+  let pretty fmt (Key (s,x)) =
+    match s.kind with
+    | Global ->
+      Format.fprintf fmt "%s" s.name
+    | Function ->
+      Format.fprintf fmt "%s:%a" s.name Kernel_function.pretty x
+    | Statement ->
+      let loc = Cil_datatype.Stmt.loc x in
+      Format.fprintf fmt "%s:%a" s.name Cil_datatype.Location.pretty loc
+end
+
+module Key = struct
+  include Datatype.Make_with_collections (Key_Datatype)
+
+  let name (Key (s, _x)) = s.name
+
+  let pretty_kf fmt (Key (s, x)) =
+    match s.kind with
+    | Global -> ()
+    | Function -> Kernel_function.pretty fmt x
+    | Statement -> Kernel_function.(pretty fmt (find_englobing_kf x))
+
+  let pretty_stmt fmt (Key (s, x)) =
+    match s.kind with
+    | Global | Function -> ()
+    | Statement -> Cil_datatype.Location.pretty fmt (Cil_datatype.Stmt.loc x)
+end
+
+(* --- Projectified state --- *)
+
+module State =
+  State_builder.Hashtbl
+    (Key.Hashtbl)
+    (Datatype.Int)
+    (struct
+      let name = "Eva.Statistics.State"
+      let dependencies = [ Self.state ]
+      let size = 17
+    end)
+
+
+(* --- Statistics update --- *)
+
+let set (type a) (stat : a t) (x : a) value =
+  let k = Key (stat,x) in
+  State.replace k value
+
+let update (type a) (stat : a t) (x : a) (f : int -> int) =
+  let k = Key (stat,x) in
+  State.replace k (f (State.find_opt k |> Option.value ~default:0))
+
+let incr (type a) (stat : a t) (x : a) =
+  update stat x (fun v -> v + 1)
+
+let grow (type a) (stat : a t) (x : a) value =
+  update stat x (fun v -> max v value)
+
+let reset_all () =
+  State.clear ()
+
+
+(* -- Export --- *)
+
+let export_as_list () =
+  State.to_seq () |> List.of_seq |>
+  List.sort (fun (k1,_v1) (k2,_v2) -> Key.compare k1 k2)
+
+let export_as_csv_to_channel out_channel =
+  let fmt = Format.formatter_of_out_channel out_channel in
+  let l = export_as_list () in
+  let pp_stat fmt (key, value) =
+    Format.fprintf fmt "%s\t%a\t%a\t%d\n"
+      (Key.name key)
+      Key.pretty_kf key
+      Key.pretty_stmt key
+      value
+  in
+  List.iter (pp_stat fmt) l
+
+let export_as_csv_to_file filename =
+  let out_channel = open_out (filename : Filepath.Normalized.t :> string) in
+  export_as_csv_to_channel out_channel
+
+let export_as_csv ?filename () =
+  match filename with
+  | None ->
+    if not (Parameters.StatisticsFile.is_empty ()) then
+      let filename = Parameters.StatisticsFile.get () in
+      export_as_csv_to_file filename
+  | Some filename ->
+    export_as_csv_to_file filename
diff --git a/src/plugins/gui/dgraph_helper.no.ml b/src/plugins/eva/utils/statistics.mli
similarity index 70%
rename from src/plugins/gui/dgraph_helper.no.ml
rename to src/plugins/eva/utils/statistics.mli
index 14eba81d27164f539ed3a8a2ae3503d340e2db7f..ca402e73218f526d265cf2b19a624bc27910b93a 100644
--- a/src/plugins/gui/dgraph_helper.no.ml
+++ b/src/plugins/eva/utils/statistics.mli
@@ -20,21 +20,24 @@
 (*                                                                        *)
 (**************************************************************************)
 
-let window_msg_unavailable () =
-  let buttons = GWindow.Buttons.ok in
-  let message_type = `WARNING in
-  let message =
-    "Frama-C has not been compiled against a library with \
-     working graph visualization. Property dependencies graph can't be shown."
-  in
-  let dialog =
-    GWindow.message_dialog ~buttons ~show:true ~message_type ~message ()
-  in
-  let callback _ = dialog#destroy () in
-  ignore (dialog#connect#response ~callback)
+type 'a t
 
-let graph_window ~parent:_ ~title:_ _ =
-  window_msg_unavailable ()
+(* Register a statistic class *)
+val register_global_stat : string -> unit t
+val register_function_stat : string -> Cil_types.kernel_function t
+val register_statement_stat : string -> Cil_types.stmt t
 
-let graph_window_through_dot ~parent:_ ~title:_ _ =
-  window_msg_unavailable ()
+(* Set the stat to the given value *)
+val set : 'a t -> 'a -> int -> unit
+
+(* Adds 1 to the stat or set it to 1 if undefined *)
+val incr : 'a t -> 'a -> unit
+
+(* Set the stat to the maximum between the current value and the given value *)
+val grow : 'a t -> 'a -> int -> unit
+
+(* Reset all statistics to zero *)
+val reset_all: unit -> unit
+
+(* Export the computed statistics as CSV *)
+val export_as_csv : ?filename:Filepath.Normalized.t -> unit -> unit
diff --git a/src/plugins/gui/GSourceView.3.ml b/src/plugins/gui/GSourceView.ml
similarity index 100%
rename from src/plugins/gui/GSourceView.3.ml
rename to src/plugins/gui/GSourceView.ml
diff --git a/src/plugins/gui/GSourceView.3.mli b/src/plugins/gui/GSourceView.mli
similarity index 100%
rename from src/plugins/gui/GSourceView.3.mli
rename to src/plugins/gui/GSourceView.mli
diff --git a/src/plugins/gui/debug_manager.ok.ml b/src/plugins/gui/debug_manager.ok.ml
deleted file mode 100644
index 94453da44d22430360722bd12ab3d4b41139a4b1..0000000000000000000000000000000000000000
--- a/src/plugins/gui/debug_manager.ok.ml
+++ /dev/null
@@ -1,79 +0,0 @@
-(**************************************************************************)
-(*                                                                        *)
-(*  This file is part of Frama-C.                                         *)
-(*                                                                        *)
-(*  Copyright (C) 2007-2023                                               *)
-(*    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 Dgraph included in OCamlgraph/Ocamlgraph_gtk, thus GnomeCanvas *)
-
-open DGRAPH_MODULE
-
-let graph_view ~packing mk_dot =
-  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
-       ~status:DGraphContainer.Global
-       ~packing
-       f)
-
-let state_dependency_graph ~packing () =
-  graph_view ~packing State_dependency_graph.dump
-
-(* [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
-  let width = int_of_float (float main_window#default_width *. 3. /. 4.) in
-  let window =
-    GWindow.window ~width ~height ~title ~resizable:true ~position:`CENTER ()
-  in
-  let view = mk_view ~packing:window#add () in
-  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 () -> Gui_parameters.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:
-compile-command: "make -C ../../.."
-End:
-*)
diff --git a/src/plugins/gui/design.ml b/src/plugins/gui/design.ml
index fe652f9a031e25d469d9d157905c5d17c10593bb..d9e13758325b50ceeb393c0d654d61e97542e8bb 100644
--- a/src/plugins/gui/design.ml
+++ b/src/plugins/gui/design.ml
@@ -854,7 +854,7 @@ class main_window () : main_window_extension_points =
       width, if final_h then height else new_height
   in
   let main_window =
-    Gtk_compat.window
+    GWindow.window
       ?icon:framac_icon
       ~title:"Frama-C"
       ~position:`CENTER
diff --git a/src/plugins/gui/dune b/src/plugins/gui/dune
index aaeb10faf883bcfc3eefb69390af8f4a7328acf7..eb4fd75ad7130dcc2296fab28e96f71f65fc8e59 100644
--- a/src/plugins/gui/dune
+++ b/src/plugins/gui/dune
@@ -25,9 +25,6 @@
  (deps (universe))
  (action (progn
           (echo "GUI:" %{lib-available:frama-c.gui} "\n")
-          (echo "  - lablgtk2:" %{lib-available:lablgtk2} "\n")
-          (echo "  - lablgtk2.gnomecanvas:" %{lib-available:lablgtk2.gnomecanvas} "\n")
-          (echo "  - lablgtk2.sourceview2:" %{lib-available:lablgtk2.sourceview2} "\n")
           (echo "  - lablgtk3:" %{lib-available:lablgtk3} "\n")
           (echo "  - lablgtk3-sourceview3:" %{lib-available:lablgtk3-sourceview3} "\n")
           ; From a GUI hook registered by RteGen.
@@ -42,44 +39,6 @@
   (name frama_c_gui)
   (public_name frama-c.gui)
   (optional)
-  (modules
-        wutil wutil_once widget wbox wfile wpane wpalette wtext wtable
-        gui_parameters
-        gtk_helper gtk_form
-        source_viewer pretty_source source_manager book_manager
-        warning_manager
-        filetree
-        launcher
-        menu_manager
-        history
-        gui_printers
-        design
-        analyses_manager file_manager project_manager
-        help_manager
-        property_navigator GSourceView gtk_compat
-        dgraph_helper
-)
   (flags -open Frama_c_kernel -linkall :standard -w -9)
-  (libraries frama-c.init.gui frama-c.kernel
-   (select gtk_compat.ml from
-      (lablgtk3 lablgtk3-sourceview3 -> gtk_compat.3.ml)
-      (lablgtk2 lablgtk2.gnomecanvas lablgtk2.sourceview2 -> gtk_compat.2.ml)
-   )
-   (select GSourceView.ml from
-      (lablgtk3 lablgtk3-sourceview3 -> GSourceView.3.ml)
-      (lablgtk2 lablgtk2.gnomecanvas lablgtk2.sourceview2 -> GSourceView.2.ml)
-   )
-   (select GSourceView.mli from
-      (lablgtk3 lablgtk3-sourceview3 -> GSourceView.3.mli)
-      (lablgtk2 lablgtk2.gnomecanvas lablgtk2.sourceview2 -> GSourceView.2.mli)
-   )
-   (select dgraph_helper.ml from
-      (!lablgtk3-sourceview3 ocamlgraph.dgraph -> dgraph_helper.yes.ml)
-      ( -> dgraph_helper.no.ml)
-   )
-   (select debug_manager.ml from
-      (!lablgtk3-sourceview3 ocamlgraph.dgraph -> debug_manager.ok.ml)
-      ( -> debug_manager.ko.ml)
-   )
-)
+  (libraries frama-c.init.gui frama-c.kernel lablgtk3 lablgtk3-sourceview3)
 )
diff --git a/src/plugins/gui/gtk_compat.2.ml b/src/plugins/gui/gtk_compat.2.ml
deleted file mode 100644
index 68b113a4127ca8e9db29b94fc700ef27d1c92856..0000000000000000000000000000000000000000
--- a/src/plugins/gui/gtk_compat.2.ml
+++ /dev/null
@@ -1,74 +0,0 @@
-(**************************************************************************)
-(*                                                                        *)
-(*  This file is part of Frama-C.                                         *)
-(*                                                                        *)
-(*  Copyright (C) 2007-2023                                               *)
-(*    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 Pango = struct
-  open Wutil_once
-
-  let small_font =
-    once (fun f ->
-        let f = Pango.Font.copy f in
-        let s = Pango.Font.get_size f in
-        Pango.Font.set_size f (s-2) ; f)
-
-  let bold_font =
-    once (fun f ->
-        let f = Pango.Font.copy f in
-        Pango.Font.set_weight f `BOLD ; f)
-
-  let modify_font phi widget =
-    widget#misc#modify_font (phi widget#misc#pango_context#font_description)
-
-  let set_small_font w = modify_font small_font w
-  let set_bold_font w = modify_font bold_font w
-end
-
-let get_toolbar_index (toolbar:GButton.toolbar) (item:GButton.tool_item) =
-  toolbar#get_item_index item
-
-let window
-    ?(kind:Gtk.Tags.window_type option)
-    ?(title:string option)
-    ?(decorated:bool option)
-    ?(deletable:bool option)
-    ?(focus_on_map:bool option)
-    ?(icon:GdkPixbuf.pixbuf option)
-    ?(icon_name:string option)
-    ?(modal:bool option)
-    ?(position:Gtk.Tags.window_position option)
-    ?(resizable:bool option)
-    ?(screen:Gdk.screen option)
-    ?(type_hint:Gdk.Tags.window_type_hint option)
-    ?(urgency_hint:bool option)
-    ?(wmclass:(string * string) option)
-    ?(border_width:int option)
-    ?(width:int option)
-    ?(height:int option)
-    ?(show:bool option)
-    ()
-  =
-  let allow_shrink = resizable in
-  let allow_grow = resizable in
-  ignore wmclass;
-  GWindow.window
-    ?kind ?title ?decorated ?deletable ?focus_on_map ?icon ?icon_name
-    ?modal ?position ?resizable ?allow_grow ?allow_shrink ?screen
-    ?type_hint ?urgency_hint ?border_width ?width ?height ?show ()
diff --git a/src/plugins/gui/help_manager.ml b/src/plugins/gui/help_manager.ml
index 5a9f2a5d04cae97f1fb2b0a96af33e62b3c49efe..d0e1fedf9ea17fd08e0c576e6348fef59e01418b 100644
--- a/src/plugins/gui/help_manager.ml
+++ b/src/plugins/gui/help_manager.ml
@@ -43,6 +43,7 @@ let show main_ui =
     "Philippe Herrmann";
     "Maxime Jacquemin";
     "Florent Kirchner";
+    "Alexander Kogtenkov";
     "Tristan Le Gall";
     "Jean-Christophe Léchenet";
     "Matthieu Lemerre";
@@ -63,6 +64,7 @@ let show main_ui =
     "Armand Puccetti";
     "Félix Ridoux";
     "Virgile Robles";
+    "Jan Rochel";
     "Muriel Roger";
     "Julien Signoles";
     "Nicolas Stouls";
diff --git a/src/plugins/gui/menu_manager.ml b/src/plugins/gui/menu_manager.ml
index 86429c985623cbfb393970ba5a5c3a9e4feb21f2..26fc68df230d6d2aaac763921a1e6df2e4553232 100644
--- a/src/plugins/gui/menu_manager.ml
+++ b/src/plugins/gui/menu_manager.ml
@@ -168,7 +168,7 @@ class menu_manager ?packing (_:Gtk_helper.host) =
             | None, Some sep ->
               max
                 0
-                (Gtk_compat.get_toolbar_index toolbar (sep:>GButton.tool_item))
+                (toolbar#get_item_index (sep:>GButton.tool_item)#as_tool_item)
             | Some p, _ -> p)
       in
       let toolbar_packing w =
diff --git a/src/plugins/gui/property_navigator.ml b/src/plugins/gui/property_navigator.ml
index 4423a1d43b266f2f75872708276333c0d06368c0..3f874465f59b47884281ad734ce6e00f19b98259 100644
--- a/src/plugins/gui/property_navigator.ml
+++ b/src/plugins/gui/property_navigator.ml
@@ -564,16 +564,6 @@ let make_panel (main_ui:main_window_extension_points) =
       ~headers_visible:true
       ~packing:sc#add ()
   in
-  ignore
-    (view#connect#row_activated
-       ~callback:(fun path _col ->
-           match model#custom_get_iter path with
-           | Some { MODEL.finfo = { ip = ip } } ->
-             let format_graph ppf =
-               Consolidation_graph.dump (Consolidation_graph.get ip) ppf in
-             Dgraph_helper.graph_window_through_dot
-               ~parent:main_ui#main_window ~title:"Dependencies" format_graph
-           | None -> ()));
   view#selection#set_select_function
     (fun path currently_selected ->
        if not currently_selected then
diff --git a/src/plugins/gui/wutil.ml b/src/plugins/gui/wutil.ml
index 995b4af8f4e8d48440e23e439e21c030fa6bf631..e0f404a42ce0d7abf8b4f3dbf3f77fb34dbd5ac5 100644
--- a/src/plugins/gui/wutil.ml
+++ b/src/plugins/gui/wutil.ml
@@ -32,8 +32,23 @@ let once = Wutil_once.once
 (* ---  Pango Properties                                                  --- *)
 (* -------------------------------------------------------------------------- *)
 
-include Gtk_compat.Pango
-
+let small_font =
+  once (fun (f: GPango.font_description) ->
+      let f = f#copy in
+      let size = f#size - 2 in
+      f#modify ~size (); f)
+
+let bold_font =
+  once (fun (f: GPango.font_description) ->
+      let f = f#copy in
+      let weight = `BOLD in
+      f#modify ~weight (); f)
+
+let modify_font phi (widget: #GObj.widget) =
+  widget#misc#modify_font (phi widget#misc#pango_context#font_description)
+
+let set_small_font w = modify_font small_font w
+let set_bold_font w = modify_font bold_font w
 let set_font w name = w#misc#modify_font_by_name name
 let set_monospace w = set_font w "monospace"
 
diff --git a/src/plugins/impact/compute_impact.ml b/src/plugins/impact/compute_impact.ml
index 66da42c04b433b1daff3572074ee3a0c0a109373..6f78536af6a6deb3c7e433fab4d0ca57dc01c4f5 100644
--- a/src/plugins/impact/compute_impact.ml
+++ b/src/plugins/impact/compute_impact.ml
@@ -711,7 +711,7 @@ let skip () =
       (fun name l ->
          let vi =
            try
-             Base.of_varinfo (Globals.Vars.find_from_astinfo name VGlobal)
+             Base.of_varinfo (Globals.Vars.find_from_astinfo name Global)
            with Not_found ->
              if name = "NULL" then Base.null
              else
diff --git a/src/plugins/impact/gui/register_gui.ml b/src/plugins/impact/gui/register_gui.ml
index 2158d07c4c481d2b1b6262117052a26de99687d1..640c23d7428cbb0f2a4283a84be9f1ca947e1284 100644
--- a/src/plugins/impact/gui/register_gui.ml
+++ b/src/plugins/impact/gui/register_gui.ml
@@ -158,17 +158,6 @@ let impact_highlighter buffer loc ~start ~stop =
     in
     apply_on_stmt hilight loc
 
-let reason_graph_window parent ?in_kf reason =
-  try
-    let mk_dot_file = Reason_graph.to_dot_formatter ?in_kf reason in
-    Dgraph_helper.graph_window_through_dot
-      ~parent ~title:"Impact graph" mk_dot_file
-  with
-  | Sys_error _ as exn ->
-    Options.error "issue when generating impact graph: %s"
-      (Printexc.to_string exn)
-
-
 let impact_statement restrict s =
   let kf = Kernel_function.find_englobing_kf s in
   let skip = Compute_impact.skip () in
@@ -216,12 +205,6 @@ let impact_statement_ui (main_ui:Design.main_window_extension_points) s =
     main_ui#rehighlight ()
   )
 
-let impact_graph_of_function (main_ui:Design.main_window_extension_points) kf =
-  let g = ReasonGraph.get () in
-  let open Reason_graph in
-  if not (Reason.Set.is_empty g.reason_graph) then
-    reason_graph_window main_ui#main_window ~in_kf:kf g
-
 let pretty_info = ref true
 
 let pp_impact_on_inputs (main_ui:Design.main_window_extension_points) kf =
@@ -297,14 +280,6 @@ let impact_selector
     if button = 3 || FollowFocus.get () then (
       let callback () = ignore (impact_statement_ui main_ui s) in
       ignore (popup_factory#add_item "_Impact analysis" ~callback);
-      if Options.Reason.get ()then begin
-        let g = ReasonGraph.get () in
-        if not Reason_graph.(Reason.Set.is_empty g.reason_graph) then begin
-          let callback () =
-            reason_graph_window main_ui#main_window ~in_kf:kf g in
-          ignore (popup_factory#add_item "Impact _graph" ~callback);
-        end;
-      end;
       if FollowFocus.get () then
         ignore (Glib.Idle.add (fun () -> callback (); false))
     );
@@ -328,14 +303,6 @@ let impact_selector
       let kf = Globals.Functions.get vi in
       pp_impact_on_inputs main_ui kf;
     end;
-    if button = 3 then begin
-      let g = ReasonGraph.get () in
-      let open Reason_graph in
-      if not (Reason.Set.is_empty g.reason_graph) then
-        let kf = Globals.Functions.get vi in
-        let callback () = impact_graph_of_function main_ui kf in
-        ignore (popup_factory#add_item "_Impact graph" ~callback);
-    end
   | _ -> ()
 
 let impact_panel main_ui =
diff --git a/src/plugins/instantiate/global_context.ml b/src/plugins/instantiate/global_context.ml
index 178fb6d0cb4afe7a79391442f4ea3c2c5e689f75..c48802ba74273d601e294059d137cdd30e98cb7e 100644
--- a/src/plugins/instantiate/global_context.ml
+++ b/src/plugins/instantiate/global_context.ml
@@ -29,7 +29,7 @@ let axiomatics = Table.create 13
 let get_variable name make =
   if Table.mem varinfos name then Table.find varinfos name
   else begin
-    try Globals.Vars.find_from_astinfo name VGlobal
+    try Globals.Vars.find_from_astinfo name Global
     with Not_found ->
       let vi = make () in
       Table.add varinfos name vi ;
diff --git a/src/plugins/markdown-report/tests/sarif/oracle/std_string.sarif b/src/plugins/markdown-report/tests/sarif/oracle/std_string.sarif
index 8df66b349d84643bc8b6e4ba28cf9e3d3517eee6..1e15a794fc46bf3b502bb9f2a30f7f41ee3db199 100644
--- a/src/plugins/markdown-report/tests/sarif/oracle/std_string.sarif
+++ b/src/plugins/markdown-report/tests/sarif/oracle/std_string.sarif
@@ -7278,8 +7278,8 @@
                   "startLine": 613,
                   "startColumn": 30,
                   "endLine": 613,
-                  "endColumn": 61,
-                  "byteLength": 31
+                  "endColumn": 62,
+                  "byteLength": 32
                 }
               }
             }
@@ -7746,8 +7746,8 @@
                   "startLine": 627,
                   "startColumn": 30,
                   "endLine": 627,
-                  "endColumn": 63,
-                  "byteLength": 33
+                  "endColumn": 64,
+                  "byteLength": 34
                 }
               }
             }
diff --git a/src/plugins/server/kernel_ast.ml b/src/plugins/server/kernel_ast.ml
index 0cfafb80824a07954033b64b754e8bc9cab341e2..df5fc860bc5bbaad1dc850a7101a8f5cf9797303 100644
--- a/src/plugins/server/kernel_ast.ml
+++ b/src/plugins/server/kernel_ast.ml
@@ -40,11 +40,16 @@ let () = Request.register ~package
 let changed_signal = Request.signal ~package ~name:"changed"
     ~descr:(Md.plain "Emitted when the AST has been changed")
 
+let ast_changed () = Request.emit changed_signal
+
 let ast_update_hook f =
-  Ast.add_hook_on_update f;
-  Ast.apply_after_computed (fun _ -> f ())
+  begin
+    Ast.add_hook_on_update f;
+    Ast.apply_after_computed (fun _ -> f ());
+  end
 
-let () = ast_update_hook (fun _ -> Request.emit changed_signal)
+let () = ast_update_hook ast_changed
+let () = Annotations.add_hook_on_change ast_changed
 
 (* -------------------------------------------------------------------------- *)
 (* --- File Positions                                                     --- *)
@@ -200,7 +205,8 @@ struct
   let to_json loc = `String (tag loc)
   let of_json js =
     try find (Js.to_string js)
-    with Not_found -> Data.failure "not a localizable marker"
+    with Not_found ->
+      Data.failure "invalid marker (%a)" Json.pp_dump js
 
 end
 
@@ -320,6 +326,13 @@ struct
     | Some vi -> Globals.Functions.mem vi
     | None -> false
 
+  let is_function_pointer = function
+    | PLval (_, _, (Mem _, NoOffset as lval))
+      when Cil.(isFunctionType (typeOfLval lval)) -> true
+    | PLval (_, _, lval)
+      when Cil.(isFunPtrType (Cil.typeOfLval lval)) -> true
+    | _ -> false
+
   let is_fundecl = function
     | PVDecl(Some _,Kglobal,vi) -> vi.vglob && Globals.Functions.mem vi
     | _ -> false
@@ -377,6 +390,14 @@ struct
       ~get:(fun (tag, _) -> is_function tag)
       model
 
+  let () =
+    States.column
+      ~name:"isFunctionPointer"
+      ~descr:(Md.plain "Whether it is a function pointer")
+      ~data:(module Jbool)
+      ~get:(fun (tag, _) -> is_function_pointer tag)
+      model
+
   let () =
     States.column
       ~name:"isFunDecl"
@@ -394,11 +415,15 @@ struct
       model
 
   let () =
-    States.column
+    let get (tag, _) =
+      let pos = fst (Printer_tag.loc_of_localizable tag) in
+      if Cil_datatype.Position.(equal unknown pos) then None else Some pos
+    in
+    States.option
       ~name:"sloc"
       ~descr:(Md.plain "Source location")
       ~data:(module Position)
-      ~get:(fun (tag, _) -> fst (Printer_tag.loc_of_localizable tag))
+      ~get
       model
 
   let array = States.register_array
@@ -442,6 +467,7 @@ let () = Request.register ~package
 let () = Request.register ~package
     ~kind:`GET ~name:"printFunction"
     ~descr:(Md.plain "Print the AST of a function")
+    ~signals:[changed_signal]
     ~input:(module Function) ~output:(module Jtext)
     begin fun kf ->
       let libc = Kernel.PrintLibc.get () in
@@ -474,9 +500,9 @@ struct
   let is_builtin kf =
     Cil_builtins.is_builtin (Kernel_function.get_vi kf)
 
-  let is_stdlib kf =
+  let is_extern kf =
     let vi = Kernel_function.get_vi kf in
-    Cil.is_in_libc vi.vattr
+    vi.vstorage = Extern
 
   let iter f =
     Globals.Functions.iter
@@ -514,13 +540,19 @@ struct
         ~descr:(Md.plain "Is the function from the Frama-C stdlib?")
         ~data:(module Data.Jbool)
         ~default:false
-        ~get:is_stdlib;
+        ~get:Kernel_function.is_in_libc;
       States.column model
         ~name:"builtin"
         ~descr:(Md.plain "Is the function a Frama-C builtin?")
         ~data:(module Data.Jbool)
         ~default:false
         ~get:is_builtin;
+      States.column model
+        ~name:"extern"
+        ~descr:(Md.plain "Is the function extern?")
+        ~data:(module Data.Jbool)
+        ~default:false
+        ~get:is_extern;
       States.column model
         ~name:"sloc"
         ~descr:(Md.plain "Source location")
diff --git a/src/plugins/server/states.ml b/src/plugins/server/states.ml
index 005896b6ed5f566bf0189fb0b60a27e0408f9e7d..00b346c51657caf06acd642c091d0325cce252b5 100644
--- a/src/plugins/server/states.ml
+++ b/src/plugins/server/states.ml
@@ -22,22 +22,25 @@
 
 open Data
 
+(* -------------------------------------------------------------------------- *)
+(* --- Hooks                                                              --- *)
+(* -------------------------------------------------------------------------- *)
+
 type 'a callback = ('a -> unit) -> unit
 
-let install signal hook = function
-  | None -> ()
-  | Some add_hook ->
-    let once = ref true in
-    let install ok =
-      if ok && !once then
-        begin
-          once := false ;
-          add_hook hook ;
-        end
-    in Request.on_signal signal install
-
-let install_emit signal add_hook =
-  install signal (fun _ -> Request.emit signal) add_hook
+let install_hook signal hook add_hook =
+  let once = ref true in
+  let install ok =
+    if ok && !once then
+      begin
+        once := false ;
+        add_hook hook ;
+        Request.emit signal ;
+      end
+  in Request.on_signal signal install
+
+let register_hook signal add_hook =
+  install_hook signal (fun _ -> Request.emit signal) add_hook
 
 (* -------------------------------------------------------------------------- *)
 (* --- Values                                                             --- *)
@@ -59,7 +62,7 @@ let register_value (type a) ~package ~name ~descr
       ~package ~name:(Package.Derived.getter id).name
       ~descr:(plain "Getter for state" @ href)
       ~kind:`GET ~input:(module Junit) ~output get in
-  install_emit signal add_hook ;
+  Option.iter (register_hook signal) add_hook ;
   signal
 
 (* -------------------------------------------------------------------------- *)
@@ -85,7 +88,7 @@ let register_state (type a) ~package ~name ~descr
       ~package ~name:(Package.Derived.setter id).name
       ~descr:(plain "Setter for state" @ href)
       ~kind:`SET ~input:(module D) ~output:(module Junit) set in
-  install_emit signal add_hook ;
+  Option.iter (register_hook signal) add_hook ;
   signal
 
 (* -------------------------------------------------------------------------- *)
@@ -381,9 +384,9 @@ let register_array ~package ~name ~descr ~key
     ~kind:`GET ~input:(module Junit) ~output:(module Junit)
     (fun () -> reload array) ;
   synchronize array ;
-  install signal (update array) add_update_hook ;
-  install signal (remove array) add_remove_hook ;
-  install signal (fun () -> reload array) add_reload_hook ;
+  Option.iter (install_hook signal (update array)) add_update_hook ;
+  Option.iter (install_hook signal (remove array)) add_remove_hook ;
+  Option.iter (install_hook signal (fun () -> reload array)) add_reload_hook ;
   array
 
 (* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/server/states.mli b/src/plugins/server/states.mli
index 21d7deb7882939536c0400ccd77354f99f2d6a13..947c2a424edd71367a0c205eabd2d4ac84cf8f35 100644
--- a/src/plugins/server/states.mli
+++ b/src/plugins/server/states.mli
@@ -26,6 +26,10 @@ open Package
 
 type 'a callback = ('a -> unit) -> unit
 
+(** Connect a hook registry to a signal. As soon as the signal is being
+    traced, a hook to emit the signal is registered. *)
+val register_hook : Request.signal -> 'a callback -> unit
+
 (** Register a (projectified) value and generates the associated signal and
     request:
     - Signal [<name>.sig] is emitted on value updates;
diff --git a/src/plugins/studia/Studia.ml b/src/plugins/studia/Studia.ml
index 90b7d6fcb243c3f5b47599b0dd574ee96ede36a4..d7eeebd84a2d6ce4bafe8045e92447f70790eb3d 100644
--- a/src/plugins/studia/Studia.ml
+++ b/src/plugins/studia/Studia.ml
@@ -28,18 +28,23 @@ include
   end :
    sig
      module Writes: sig
+       type t =
+         | Assign of Cil_types.stmt
+         (** Direct assignment. *)
+         | CallDirect of Cil_types.stmt
+         (** Modification by a called leaf function. *)
+         | CallIndirect of Cil_types.stmt
+         (** Modification inside the body of a called function. *)
+         | GlobalInit of Cil_types.varinfo * Cil_types.initinfo
+         (** Initialization of a global variable. *)
+         | FormalInit of
+             Cil_types.varinfo *
+             (Cil_types.kernel_function * Cil_types.stmt list) list
+         (** Initialization of a formal parameter, with a list of callsites. *)
 
-       (** Given an effect [e], something is directly modified by [e] (through an
-           affectation, or through a call to a leaf function) if [direct] holds, and
-           indirectly (through the effects of a call) otherwise.  *)
-       type effects = {
-         direct: bool (** Direct affectation [lv = ...], or modification through
-                          a call to a leaf function. *);
-         indirect: bool (** Modification inside the body of called function
-                            [f(...)]*);
-       }
-
-       val compute: Locations.Zone.t -> (Cil_types.stmt * effects) list
+       val compare: t -> t -> int
+
+       val compute: Locations.Zone.t -> t list
        (** [compute z] finds all the statements that modifies [z], and for each
            statement, indicates whether the modification is direct or indirect. *)
 
@@ -47,8 +52,13 @@ include
 
      (** Computations of the statements that read a given memory zone. *)
      module Reads: sig
+       type t =
+         | Direct of Cil_types.stmt
+         (** Direct read by a statement. *)
+         | Indirect of Cil_types.stmt
+         (** Indirect read through a function call. *)
 
-       val compute: Locations.Zone.t -> (Cil_types.stmt * Writes.effects) list
+       val compute: Locations.Zone.t -> t list
        (** [compute z] finds all the statements that read [z]. The [effects]
            information indicates whether the read occur on the given statement,
            or through an inner call for [Call] instructions. *)
diff --git a/src/plugins/studia/gui/studia_gui.ml b/src/plugins/studia/gui/studia_gui.ml
index cd82d707405d22440dd23cbfd389c5d7c55f63d2..ac71b45402b35c43c9b1dfdcbeb63232a9ce56ca 100644
--- a/src/plugins/studia/gui/studia_gui.ml
+++ b/src/plugins/studia/gui/studia_gui.ml
@@ -80,7 +80,6 @@ module Kfs_containing_highlighted_stmt =
     end)
 
 let default_icon_name = "gtk-apply"
-let default_icon = Datatype.String.Set.singleton default_icon_name
 
 
 module Make_StmtMapState (Info:sig val name: string end) =
@@ -140,29 +139,44 @@ struct
                     ^"highlight the statements that reads the location pointed to \
                       by D at L")
 
-  let indirect_icon = Datatype.String.Set.singleton "gtk-jump-to"
+  let indirect_icon_name = "gtk-jump-to"
 
-  let conv l =
-    let aux acc (stmt, effects) =
-      let empty = Datatype.String.Set.empty in
-      let direct = if effects.Writes.direct then default_icon else empty in
-      let indirect = if effects.Writes.indirect then indirect_icon else empty in
-      let s = Datatype.String.Set.union direct indirect in
-      if Datatype.String.Set.is_empty s then acc else Stmt.Map.add stmt s acc
+  let add_icon map stmt icon =
+    let update_icons pre =
+      Some(Datatype.String.Set.(add icon (Option.value ~default:empty pre)))
     in
-    List.fold_left aux Stmt.Map.empty l
+    Stmt.Map.update stmt update_icons map
+
+  let add_read map = function
+    | Reads.Direct stmt -> add_icon map stmt default_icon_name
+    | Indirect stmt -> add_icon map stmt indirect_icon_name
+
+  let add_write map = function
+    | Writes.Assign stmt
+    | CallDirect stmt -> add_icon map stmt default_icon_name
+    | CallIndirect stmt -> add_icon map stmt indirect_icon_name
+    | GlobalInit _ -> map
+    | FormalInit (_, callsites) ->
+      let calls = List.flatten (List.map snd callsites) in
+      List.fold_left
+        (fun map stmt -> add_icon map stmt default_icon_name)
+        map
+        calls
 
   let compute op _kf stmt tlv =
     let t = Logic_const.term (TLval tlv) (Cil.typeOfTermLval tlv) in
     let z = eval_tlval stmt t in
     let r, s = match op with
-      | `Reads -> Reads.compute z, "Reads"
-      | `Writes -> Writes.compute z, "Writes"
+      | `Reads ->
+        List.fold_left add_read Stmt.Map.empty (Reads.compute z), "Reads"
+      | `Writes ->
+        List.fold_left add_write Stmt.Map.empty (Writes.compute z), "Writes"
     in
+    State.set r;
     Options.feedback "%s computed" s;
-    match r with
-    | [] -> clear (); s ^ " computed; no statement found."
-    | defs -> State.set (conv defs); s ^ " computed"
+    if Stmt.Map.is_empty r
+    then s ^ " computed; no statement found."
+    else s ^ " computed"
 
   let tag_stmt stmt =
     try
diff --git a/src/plugins/studia/reads.ml b/src/plugins/studia/reads.ml
index c4920a11f573cc86e3ecbcf648f6cefb80c52ee1..3bebf797fa3bda62c11cf80191be51eec1a06226 100644
--- a/src/plugins/studia/reads.ml
+++ b/src/plugins/studia/reads.ml
@@ -25,12 +25,15 @@
 
 open Cil_types
 open Locations
-open Writes
+
+type t =
+  | Direct of Cil_types.stmt
+  | Indirect of Cil_types.stmt
 
 class find_read zlval = object
   inherit Visitor.frama_c_inplace
 
-  val mutable res = ([] : (stmt * effects) list)
+  val mutable res : t list = []
 
   method! vstmt_aux stmt =
     let aux_call lvopt _kf args _loc =
@@ -50,7 +53,7 @@ class find_read zlval = object
         let direct = Zone.intersects deps zlval in
         (* now determine if the functions called at [stmt] read directly or
              indirectly [zlval] *)
-        let aux_kf effects kf =
+        let aux_kf (direct, indirect) kf =
           let inputs = !Db.Inputs.get_internal kf in
           (* TODO: change to this once we can get "full" inputs through Inout.
              Currently, non operational inputs disappear, and this function
@@ -59,18 +62,19 @@ class find_read zlval = object
              let inputs = inout.Inout_type.over_inputs in *)
           if Zone.intersects inputs zlval then
             if Eva.Analysis.use_spec_instead_of_definition kf then
-              (* Direst, as there is no body for this funtion. *)
-              { effects with direct = true }
+              (* Direct, as there is no body for this function. *)
+              (true, indirect)
             else
-              { effects with indirect = true } (* Indirect effect *)
+              (direct, true) (* Indirect effect *)
           else
-            effects (* this function pointer does not read [zlval] *)
+            (direct, indirect) (* this function pointer does not read [zlval] *)
         in
         let kfs = Eva.Results.callee stmt in
-        let effects =
-          List.fold_left aux_kf {direct; indirect = false} kfs
-        in
-        res <- (stmt, effects) :: res
+        let direct, indirect = List.fold_left aux_kf (direct, false) kfs in
+        if direct then
+          res <- Direct stmt :: res;
+        if indirect then
+          res <- Indirect stmt :: res;
       end
     in
     match stmt.skind with
@@ -83,13 +87,13 @@ class find_read zlval = object
     | Instr _ ->
       let z = !Db.Inputs.statement stmt in
       if Zone.intersects z zlval then begin
-        res <- (stmt, {direct = true; indirect = false}) :: res
+        res <- Direct stmt :: res
       end;
       Cil.SkipChildren
     | If (e, _, _, _) | Switch (e, _, _, _) | Return (Some e, _) ->
       let z = !Db.Inputs.expr stmt e in
       if Zone.intersects z zlval then begin
-        res <- (stmt, {direct = true; indirect = false}) :: res
+        res <- Direct stmt :: res
       end;
       Cil.DoChildren
     | _ -> Cil.DoChildren
diff --git a/src/plugins/studia/reads.mli b/src/plugins/studia/reads.mli
index b219e2f283f23ded934c3fe8c3468aa72c32bbcc..e632f51cb9c51a04101e61343b1a6167163b566c 100644
--- a/src/plugins/studia/reads.mli
+++ b/src/plugins/studia/reads.mli
@@ -22,7 +22,13 @@
 
 (** Computations of the statements that read a given memory zone. *)
 
-val compute: Locations.Zone.t -> (Cil_types.stmt * Writes.effects) list
+type t =
+  | Direct of Cil_types.stmt
+  (** Direct read by a statement. *)
+  | Indirect of Cil_types.stmt
+  (** Indirect read through a function call. *)
+
+val compute: Locations.Zone.t -> t list
 (** [compute z] finds all the statements that read [z]. The [effects]
     information indicates whether the read occur on the given statement,
     or through an inner call for [Call] instructions. *)
diff --git a/src/plugins/studia/studia_request.ml b/src/plugins/studia/studia_request.ml
index f657ba818805deb8c6335b6e10a40d68917787a6..f877c39ba0b6db79432de7a162386c5ccd7567f4 100644
--- a/src/plugins/studia/studia_request.ml
+++ b/src/plugins/studia/studia_request.ml
@@ -63,22 +63,30 @@ module Effects = struct
     R.to_json
 end
 
-
-type kind = Reads | Writes
-
-let compute kind zone =
-  let stmts = match kind with
-    | Reads -> Reads.compute zone
-    | Writes -> Writes.compute zone
+let compute_writes zone =
+  let reads = Writes.compute zone in
+  let add acc = function
+    | Writes.Assign stmt | CallDirect stmt ->
+      { acc with direct = stmt :: acc.direct }
+    | CallIndirect stmt ->
+      { acc with indirect = stmt :: acc.indirect }
+    | FormalInit (_vi, callsites) ->
+      let calls = List.flatten (List.map snd callsites) in
+      { acc with direct = calls @ acc.direct }
+    | GlobalInit (_vi, _initinfo) ->
+      acc (* for now ignore global initializations *)
   in
-  let add_if b stmt acc = if b then stmt :: acc else acc in
-  let add acc (stmt, e) =
-    let direct = add_if e.Writes.direct stmt acc.direct in
-    let indirect = add_if e.Writes.indirect stmt acc.indirect in
-    { direct; indirect }
+  let empty = { direct = []; indirect = []; } in
+  List.fold_left add empty reads
+
+let compute_reads zone =
+  let reads = Reads.compute zone in
+  let add acc = function
+    | Reads.Direct stmt -> { acc with direct = stmt :: acc.direct }
+    | Indirect stmt -> { acc with indirect = stmt :: acc.indirect }
   in
   let empty = { direct = []; indirect = []; } in
-  List.fold_left add empty stmts
+  List.fold_left add empty reads
 
 let lval_location kinstr lval =
   Eva.Results.(before_kinstr kinstr |> eval_address lval |> as_zone)
@@ -88,11 +96,11 @@ let () = Request.register ~package
     ~descr:(Markdown.plain "Get the list of statements that read a lval.")
     ~input:(module Kernel_ast.Lval)
     ~output:(module Effects)
-    (fun (kinstr, lval) -> compute Reads (lval_location kinstr lval))
+    (fun (kinstr, lval) -> compute_reads (lval_location kinstr lval))
 
 let () = Request.register ~package
     ~kind:`GET ~name:"getWritesLval"
     ~descr:(Markdown.plain "Get the list of statements that write a lval.")
     ~input:(module Kernel_ast.Lval)
     ~output:(module Effects)
-    (fun (kinstr, lval) -> compute Writes (lval_location kinstr lval))
+    (fun (kinstr, lval) -> compute_writes (lval_location kinstr lval))
diff --git a/src/plugins/studia/writes.ml b/src/plugins/studia/writes.ml
index 58e71335ff2ee663684d97c38fdd0f7d2e71a46c..5958368970b0acd176334fff1d5163aecef5a54e 100644
--- a/src/plugins/studia/writes.ml
+++ b/src/plugins/studia/writes.ml
@@ -28,32 +28,61 @@
 open Cil_types
 open Locations
 
-type effects = {
-  direct: bool;
-  indirect: bool;
-}
+type t =
+  | Assign of Cil_types.stmt
+  | CallDirect of Cil_types.stmt
+  | CallIndirect of Cil_types.stmt
+  | GlobalInit of Cil_types.varinfo * Cil_types.initinfo
+  | FormalInit of
+      Cil_types.varinfo *
+      (Cil_types.kernel_function * Cil_types.stmt list) list
+
+let (<?>) c lcmp =
+  if c <> 0 then c else Lazy.force lcmp
+
+let compare w1 w2 =
+  let open Cil_datatype in
+  let module List = Transitioning.List in
+  match w1, w2 with
+  | Assign s1, Assign s2
+  | CallDirect s1, CallDirect s2
+  | CallIndirect s1, CallIndirect s2 -> Stmt.compare s1 s2
+  | GlobalInit (v1, i1), GlobalInit (v2, i2) ->
+    Varinfo.compare v1 v2 <?> lazy (Initinfo.compare i1 i2)
+  | FormalInit (v1, cs1), FormalInit (v2, cs2) ->
+    let compare_callsites (kf1, stmts1) (kf2, stmts2) =
+      Kf.compare kf1 kf2 <?> lazy (List.compare Stmt.compare stmts1 stmts2)
+    in
+    Varinfo.compare v1 v2 <?> lazy (List.compare compare_callsites cs1 cs2)
+  | Assign _, _ -> 1
+  | _, Assign _ -> -1
+  | CallDirect _, _ -> 1
+  | _, CallDirect _ -> -1
+  | CallIndirect _, _ -> 1
+  | _, CallIndirect _ -> -1
+  | GlobalInit _, _ -> 1
+  | _, GlobalInit _ -> -1
 
 (** Does the functions called at [stmt] modify directly or indirectly [zlval] *)
 let effects_of_call stmt zlval effects  =
-  let aux_kf effects kf =
+  let aux_kf (direct, indirect) kf =
     let inout = !Db.Operational_inputs.get_internal_precise ~stmt kf in
     let out = inout.Inout_type.over_outputs in
     if Zone.intersects out zlval then
       if Eva.Analysis.use_spec_instead_of_definition kf then
-        { effects with direct = true } (* Mark the effect as direct, there is
-                                          no body for this funtion. *)
+        (true, indirect) (* Direct effect: there is no body for this funtion. *)
       else
-        { effects with indirect = true } (* Indirect effect *)
+        (direct, true) (* Indirect effect *)
     else
-      effects
+      (direct, indirect)
   in
   let kfs = Eva.Results.callee stmt in
   List.fold_left aux_kf effects kfs
 
-class find_write zlval = object (self)
+class find_write_insts zlval = object (self)
   inherit Visitor.frama_c_inplace
 
-  val mutable res = ([] : (stmt * effects) list)
+  val mutable res : t list = []
 
   method! vinst i =
     let stmt = Option.get self#current_stmt in
@@ -63,23 +92,24 @@ class find_write zlval = object (self)
            the call. *)
         let z = !Db.Outputs.statement stmt in
         if Zone.intersects z zlval then
-          let direct_write = match lvopt with
+          let direct = match lvopt with
             | None -> false
             | Some lv ->
               Eva.Results.(before stmt |> eval_address lv |> as_zone_result) |>
               Result.fold ~ok:(Zone.intersects zlval) ~error:(fun _ -> false)
           in
-          let effects =
-            effects_of_call stmt zlval {direct = direct_write; indirect =false}
-          in
-          res <- (stmt, effects) :: res
+          let direct, indirect = effects_of_call stmt zlval (direct, false) in
+          if direct then
+            res <- CallDirect stmt :: res;
+          if indirect then
+            res <- CallIndirect stmt :: res;
       in
       match i with
       | Set _ | Local_init(_, AssignInit _, _) ->
         (* Effect only throuh the written l-value *)
         let z = !Db.Outputs.statement stmt in
         if Zone.intersects z zlval then begin
-          res <- (stmt, {direct = true; indirect = false}) :: res
+          res <- Assign stmt :: res
         end
       | Call (lvopt, f, args, loc) -> aux_call lvopt f args loc
       | Local_init(v, ConsInit(f, args, k), l) ->
@@ -91,8 +121,8 @@ class find_write zlval = object (self)
   method result = res
 end
 
-let compute z =
-  let vis = new find_write z in
+let inst_writes z =
+  let vis = new find_write_insts z in
   let aux_kf_fundec kf =
     let all_out = !Db.Operational_inputs.get_internal_precise kf in
     let zout = all_out.Inout_type.over_outputs in
@@ -107,3 +137,18 @@ let compute z =
   in
   Globals.Functions.iter aux_kf;
   vis#result
+
+let base_inits base acc =
+  match Base.to_varinfo base with
+  | exception Base.Not_a_C_variable -> acc
+  | vi when vi.vglob ->
+    let initinfo = Globals.Vars.find vi in
+    GlobalInit (vi, initinfo) :: acc
+  | vi when vi.vformal ->
+    let kf = Option.get (Kernel_function.find_defining_kf vi) in
+    let callsites = Eva.Results.callsites kf in
+    FormalInit (vi, callsites) :: acc
+  | _ -> acc (* Local init will be found by [inst_writes] *)
+
+let compute z =
+  inst_writes z @ Zone.fold_bases base_inits z []
diff --git a/src/plugins/studia/writes.mli b/src/plugins/studia/writes.mli
index 1e71e184973f09cc4c6798eea0f114ed31ecee4d..8bb6e8bdb9732463f60e92ce9ec39662f4d92d7d 100644
--- a/src/plugins/studia/writes.mli
+++ b/src/plugins/studia/writes.mli
@@ -22,15 +22,22 @@
 
 (** Computations of the statements that write a given memory zone. *)
 
-(** Given an effect [e], something is directly modified by [e] (through an
-    affectation, or through a call to a leaf function) if [direct] holds, and
-    indirectly (through the effects of a call) otherwise.  *)
-type effects = {
-  direct: bool (** Direct affectation [lv = ...], or modification through
-                   a call to a leaf function. *);
-  indirect: bool (** Modification inside the body of called function [f(...)]*);
-}
+type t =
+  | Assign of Cil_types.stmt
+  (** Direct assignment. *)
+  | CallDirect of Cil_types.stmt
+  (** Modification by a called leaf function. *)
+  | CallIndirect of Cil_types.stmt
+  (** Modification inside the body of a called function. *)
+  | GlobalInit of Cil_types.varinfo * Cil_types.initinfo
+  (** Initialization of a global variable. *)
+  | FormalInit of
+      Cil_types.varinfo *
+      (Cil_types.kernel_function * Cil_types.stmt list) list
+  (** Initialization of a formal parameter, with a list of callsites. *)
 
-val compute: Locations.Zone.t -> (Cil_types.stmt * effects) list
+val compare: t -> t -> int
+
+val compute: Locations.Zone.t -> t list
 (** [compute z] finds all the statements that modifies [z], and for each
     statement, indicates whether the modification is direct or indirect. *)
diff --git a/src/plugins/variadic/tests/erroneous/oracle/exec.res.oracle b/src/plugins/variadic/tests/erroneous/oracle/exec.res.oracle
index 085bd49daedba21356626eea68d343d1c78c6d25..c490429033d6bee109ace320bcb85741b8b84e64 100644
--- a/src/plugins/variadic/tests/erroneous/oracle/exec.res.oracle
+++ b/src/plugins/variadic/tests/erroneous/oracle/exec.res.oracle
@@ -1,8 +1,8 @@
-[variadic] FRAMAC_SHARE/libc/unistd.h:800: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:807: 
   Declaration of variadic function execl.
-[variadic] FRAMAC_SHARE/libc/unistd.h:805: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:812: 
   Declaration of variadic function execle.
-[variadic] FRAMAC_SHARE/libc/unistd.h:810: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:817: 
   Declaration of variadic function execlp.
 [variadic:typing] exec.c:5: Warning: 
   Incorrect type for argument 3. The argument will be cast from int to char *.
diff --git a/src/plugins/variadic/tests/known/oracle/exec.res.oracle b/src/plugins/variadic/tests/known/oracle/exec.res.oracle
index d8d3c2140b9386b1b0c6a2afaf849ff544614822..f0bfef85da9002bc9642c397b3102812e008369b 100644
--- a/src/plugins/variadic/tests/known/oracle/exec.res.oracle
+++ b/src/plugins/variadic/tests/known/oracle/exec.res.oracle
@@ -1,8 +1,8 @@
-[variadic] FRAMAC_SHARE/libc/unistd.h:800: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:807: 
   Declaration of variadic function execl.
-[variadic] FRAMAC_SHARE/libc/unistd.h:805: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:812: 
   Declaration of variadic function execle.
-[variadic] FRAMAC_SHARE/libc/unistd.h:810: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:817: 
   Declaration of variadic function execlp.
 [variadic] exec.c:9: Translating call to execle to a call to execve.
 [variadic:typing] exec.c:11: Warning: 
diff --git a/src/plugins/variadic/tests/known/oracle/exec_failed_requirement.res.oracle b/src/plugins/variadic/tests/known/oracle/exec_failed_requirement.res.oracle
index 1304870fba51e541b9e5f3b40786a6c0ce6ca7aa..3d9efbe798806b409376f8f17c78a10d34e509c1 100644
--- a/src/plugins/variadic/tests/known/oracle/exec_failed_requirement.res.oracle
+++ b/src/plugins/variadic/tests/known/oracle/exec_failed_requirement.res.oracle
@@ -1,8 +1,8 @@
-[variadic] FRAMAC_SHARE/libc/unistd.h:800: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:807: 
   Declaration of variadic function execl.
-[variadic] FRAMAC_SHARE/libc/unistd.h:805: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:812: 
   Declaration of variadic function execle.
-[variadic] FRAMAC_SHARE/libc/unistd.h:810: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:817: 
   Declaration of variadic function execlp.
 [variadic] exec_failed_requirement.c:7: 
   Translating call to execl to a call to execv.
diff --git a/src/plugins/variadic/tests/known/oracle/printf.res.oracle b/src/plugins/variadic/tests/known/oracle/printf.res.oracle
index 7ee761f24d504c42269186b8ff7fffa29191c376..91a4df4a5fabb46de2645a409d2f0f21e0c1f7f7 100644
--- a/src/plugins/variadic/tests/known/oracle/printf.res.oracle
+++ b/src/plugins/variadic/tests/known/oracle/printf.res.oracle
@@ -509,7 +509,7 @@ int printf_va_21(char const * restrict format, unsigned long param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_22(char const * restrict format, int param0);
+int printf_va_22(char const * restrict format, long param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -617,8 +617,8 @@ int main(void)
   size_t z;
   ptrdiff_t t;
   char *string = (char *)"Hello world !\n";
-  wchar_t *wstring = L"H" "e" "l" "l" "o" " " "w" "o" "r" "l" "d" " " "!"
-    "\\n" ;
+  wchar_t *wstring = (wchar_t *)L"H" "e" "l" "l" "o" " " "w" "o" "r" "l" "d"
+    " " "!" "\\n" ;
   char c = (char)'4';
   unsigned char uhh = (unsigned char)42;
   unsigned short uh = (unsigned short)42;
@@ -631,7 +631,7 @@ int main(void)
   uint64_t u64 = 42ul;
   int8_t i8 = (int8_t)42;
   uint_least64_t uleast64 = (uint_least64_t)42u;
-  int_fast32_t ifast32 = 42;
+  int_fast32_t ifast32 = (int_fast32_t)42;
   printf("Hello world !\n"); /* printf_va_1 */
   printf("%s%n",string,& i); /* printf_va_2 */
   printf("%ls",wstring); /* printf_va_3 */
@@ -653,7 +653,7 @@ int main(void)
   printf("%lu",u64); /* printf_va_19 */
   printf("%hhi",(int)i8); /* printf_va_20 */
   printf("%lx",uleast64); /* printf_va_21 */
-  printf("%d",ifast32); /* printf_va_22 */
+  printf("%ld",ifast32); /* printf_va_22 */
   printf("%f %Le\n",f,L); /* printf_va_23 */
   printf("%c\n",(int)c); /* printf_va_24 */
   printf("%p ",(void *)string); /* printf_va_25 */
diff --git a/src/plugins/variadic/tests/known/oracle/printf_wrong_pointers.res.oracle b/src/plugins/variadic/tests/known/oracle/printf_wrong_pointers.res.oracle
index 61261c69b7f3e3af3676c8f2ecadcda889a2b9fa..9a98767e77768581ae88fd9ab8c72c787968a65c 100644
--- a/src/plugins/variadic/tests/known/oracle/printf_wrong_pointers.res.oracle
+++ b/src/plugins/variadic/tests/known/oracle/printf_wrong_pointers.res.oracle
@@ -139,7 +139,7 @@ int main(void)
   short tt;
   unsigned int ui = (unsigned int)42;
   char *string = (char *)"foo";
-  wchar_t *wstring = L"b" "a" "r" ;
+  wchar_t *wstring = (wchar_t *)L"b" "a" "r" ;
   int volatile nondet = 0;
   switch (nondet) {
     case 0: printf("%n",(int *)(& tt)); /* printf_va_1 */
diff --git a/src/plugins/variadic/tests/known/oracle/printf_wrong_types.res.oracle b/src/plugins/variadic/tests/known/oracle/printf_wrong_types.res.oracle
index 3b67607452bdcfe8fa313f2f737c266505abb507..23f119932584c4d6bbed35b7ec4336d082b6d0db 100644
--- a/src/plugins/variadic/tests/known/oracle/printf_wrong_types.res.oracle
+++ b/src/plugins/variadic/tests/known/oracle/printf_wrong_types.res.oracle
@@ -367,7 +367,7 @@ int main(void)
   f ∈ {42.}
   ld ∈ {42.}
   string ∈ {{ "42" }}
-  rc ∈ {0}
+  rc ∈ {OK}
   __retres ∈ {0}
 /* Generated by Frama-C */
 #include "errno.h"
diff --git a/src/plugins/variadic/tests/known/oracle/swprintf.res.oracle b/src/plugins/variadic/tests/known/oracle/swprintf.res.oracle
index c31c436e505d57cd2728188cdb8bad388f31249d..8af3312245852398624861dd9ce724d859bdcd50 100644
--- a/src/plugins/variadic/tests/known/oracle/swprintf.res.oracle
+++ b/src/plugins/variadic/tests/known/oracle/swprintf.res.oracle
@@ -105,11 +105,11 @@ int main(void)
   if (nondet) {
     size_t tmp;
     tmp = wcslen((wchar_t const *)(data));
-    swprintf(dest,tmp,(wchar_t const *)L"%" "l" "s" ,data); /* swprintf_va_1 */
+    swprintf(dest,tmp,L"%" "l" "s" ,data); /* swprintf_va_1 */
     /*@ assert \false; */ ;
   }
   tmp_0 = wcslen((wchar_t const *)(data));
-  swprintf(dest,tmp_0 / (size_t)2,(wchar_t const *)L"%" "l" "s" ,data); /* swprintf_va_2 */
+  swprintf(dest,tmp_0 / (size_t)2,L"%" "l" "s" ,data); /* swprintf_va_2 */
   __retres = 0;
   return __retres;
 }
diff --git a/src/plugins/variadic/tests/known/oracle/wchar.res.oracle b/src/plugins/variadic/tests/known/oracle/wchar.res.oracle
index f1a366040cbd837b60f664d8e632a2e5128fd36d..2a071e17fd01fd098b3e9d9afa7497d698bf87a0 100644
--- a/src/plugins/variadic/tests/known/oracle/wchar.res.oracle
+++ b/src/plugins/variadic/tests/known/oracle/wchar.res.oracle
@@ -256,21 +256,20 @@ int main(void)
   int j;
   wchar_t input[0x100] =
     {102, 111, 114, 116, 121, 45, 116, 119, 111, 32, 105, 115, 0};
-  wprintf((wchar_t const *)L"%" "d" " " "%" "l" "d" "\\n" ,42,42L); /* wprintf_va_1 */
-  wprintf((wchar_t const *)L"%" "1" "0" "d" " " "%" "0" "1" "0" "d" "\\n" ,
-          42,42); /* wprintf_va_2 */
-  wprintf((wchar_t const *)L"%" "d" " " "%" "x" " " "%" "o" " " "%" "#" "x"
-          " " "%" "#" "o" "\\n" ,42,42u,42u,42u,42u); /* wprintf_va_3 */
-  wprintf((wchar_t const *)L"%" "2" "." "1" "f" " " "%" "+" "." "0" "e" " "
-          "%" "E" "\\n" ,42.0,42.0,42.0); /* wprintf_va_4 */
-  wprintf((wchar_t const *)L"%" "*" "d" " " "\\n" ,4,2); /* wprintf_va_5 */
-  wprintf((wchar_t const *)L"%" "l" "s" " " "\\n" ,L"4" "2" ); /* wprintf_va_6 */
-  swprintf(wstring,(size_t)0x100,(wchar_t const *)L"%" "s" " " "=" " " "%"
-           "d" ,(char *)L"4" "2" " " "+" " " "4" "2" ,42 + 42); /* swprintf_va_1 */
-  wscanf((wchar_t const *)L"%" "l" "s" ,wstring); /* wscanf_va_1 */
-  wscanf((wchar_t const *)L"%" "d" " " "%" "d" ,& i,& j); /* wscanf_va_2 */
-  swscanf((wchar_t const *)(input),(wchar_t const *)L"%" "l" "s" " " "%" "*"
-          "s" " " "%" "d" ,wstring,& i); /* swscanf_va_1 */
+  wprintf(L"%" "d" " " "%" "l" "d" "\\n" ,42,42L); /* wprintf_va_1 */
+  wprintf(L"%" "1" "0" "d" " " "%" "0" "1" "0" "d" "\\n" ,42,42); /* wprintf_va_2 */
+  wprintf(L"%" "d" " " "%" "x" " " "%" "o" " " "%" "#" "x" " " "%" "#" "o"
+          "\\n" ,42,42u,42u,42u,42u); /* wprintf_va_3 */
+  wprintf(L"%" "2" "." "1" "f" " " "%" "+" "." "0" "e" " " "%" "E" "\\n" ,
+          42.0,42.0,42.0); /* wprintf_va_4 */
+  wprintf(L"%" "*" "d" " " "\\n" ,4,2); /* wprintf_va_5 */
+  wprintf(L"%" "l" "s" " " "\\n" ,(wchar_t *)L"4" "2" ); /* wprintf_va_6 */
+  swprintf(wstring,(size_t)0x100,L"%" "s" " " "=" " " "%" "d" ,(char *)L"4"
+           "2" " " "+" " " "4" "2" ,42 + 42); /* swprintf_va_1 */
+  wscanf(L"%" "l" "s" ,wstring); /* wscanf_va_1 */
+  wscanf(L"%" "d" " " "%" "d" ,& i,& j); /* wscanf_va_2 */
+  swscanf((wchar_t const *)(input),L"%" "l" "s" " " "%" "*" "s" " " "%" "d" ,
+          wstring,& i); /* swscanf_va_1 */
   __retres = 0;
   return __retres;
 }
diff --git a/src/plugins/wp/Auto.ml b/src/plugins/wp/Auto.ml
index e22f14b72d75e97409c511be0a785b033adba681..e2e040243ca5d34c14d347c4978dc086ec4fc813 100644
--- a/src/plugins/wp/Auto.ml
+++ b/src/plugins/wp/Auto.ml
@@ -109,6 +109,7 @@ let intuition = TacNormalForm.strategy
 let range = TacRange.strategy
 let split = TacSplit.strategy
 let definition = TacUnfold.strategy
+let compute = TacCompute.strategy
 let instance = TacInstance.strategy
 let lemma = TacLemma.strategy
 
diff --git a/src/plugins/wp/Auto.mli b/src/plugins/wp/Auto.mli
index b85f8fa008b1ae98a3154ea9d15ce6dd84dfd530..a5329fad4848a4ff9b6c56bd62983aa5fa11d1f1 100644
--- a/src/plugins/wp/Auto.mli
+++ b/src/plugins/wp/Auto.mli
@@ -43,6 +43,7 @@ val intuition : ?priority:float -> selection -> strategy
 val range : ?priority:float -> selection -> vmin:int -> vmax:int -> strategy
 val split : ?priority:float -> selection -> strategy
 val definition : ?priority:float -> selection -> strategy
+val compute : ?priority:float -> selection -> strategy
 
 (* -------------------------------------------------------------------------- *)
 (** {2 Registered Heuristics} *)
diff --git a/src/plugins/wp/Cache.ml b/src/plugins/wp/Cache.ml
index 6a60e4b06802e14ad3e7e258c436199f8208e917..247f0324a9f2996e9e96ddef70a33970fbd3fd0d 100644
--- a/src/plugins/wp/Cache.ml
+++ b/src/plugins/wp/Cache.ml
@@ -105,14 +105,6 @@ let parse_mode ~origin ~fallback = function
       "Unknown %s mode %S (use %s instead)" origin m fallback ;
     raise Not_found
 
-let mode_name = function
-  | NoCache -> "none"
-  | Update -> "update"
-  | Replay -> "replay"
-  | Rebuild -> "rebuild"
-  | Offline -> "offline"
-  | Cleanup -> "cleanup"
-
 module MODE = WpContext.StaticGenerator(Datatype.Unit)
     (struct
       type key = unit
@@ -134,7 +126,7 @@ module MODE = WpContext.StaticGenerator(Datatype.Unit)
     end)
 
 let get_mode = MODE.get
-let set_mode m = MODE.clear () ; Wp_parameters.Cache.set (mode_name m)
+let set_mode m = MODE.set () m
 
 let is_active = function
   | NoCache -> false
@@ -145,16 +137,16 @@ let is_updating = function
   | Update | Rebuild | Cleanup -> true
 
 let time_fits time = function
-  | None | Some 0 -> true
-  | Some limit -> time <= float limit
+  | None | Some 0.0 -> true
+  | Some limit -> time <= limit
 
 let steps_fits steps = function
   | None | Some 0 -> true
   | Some limit -> steps <= limit
 
 let time_seized time = function
-  | None | Some 0 -> false
-  | Some limit -> float limit <= time
+  | None | Some 0.0 -> false
+  | Some limit -> limit <= time
 
 let steps_seized steps steplimit =
   steps <> 0 &&
@@ -162,7 +154,7 @@ let steps_seized steps steplimit =
   | None | Some 0 -> false
   | Some limit -> limit <= steps
 
-let promote ~timeout ~steplimit (res : VCS.result) =
+let promote ?timeout ?steplimit (res : VCS.result) =
   match res.verdict with
   | VCS.NoResult | VCS.Computing _ -> VCS.no_result
   | VCS.Failed -> res
@@ -257,7 +249,7 @@ type 'a digest =
   Why3Provers.t -> 'a -> string
 
 type 'a runner =
-  timeout:int option -> steplimit:int option -> Why3Provers.t -> 'a ->
+  timeout:float option -> steplimit:int option -> Why3Provers.t -> 'a ->
   VCS.result Task.task
 
 let get_result ~digest ~runner ~timeout ~steplimit prover goal =
@@ -273,7 +265,7 @@ let get_result ~digest ~runner ~timeout ~steplimit prover goal =
     let hash = lazy (digest prover goal) in
     let result =
       get_cache_result ~mode hash
-      |> promote ~timeout ~steplimit |> VCS.cached in
+      |> promote ?timeout ?steplimit |> VCS.cached in
     if VCS.is_verdict result
     then
       begin
diff --git a/src/plugins/wp/Cache.mli b/src/plugins/wp/Cache.mli
index 928acecfa3d21d93fc63aec1ef9687d41b2dcae6..5ee0e5deec01408f4c1c2c5e1d9f00b1f33576e3 100644
--- a/src/plugins/wp/Cache.mli
+++ b/src/plugins/wp/Cache.mli
@@ -38,9 +38,14 @@ val cleanup_cache : unit -> unit
 type 'a digest = Why3Provers.t -> 'a -> string
 
 type 'a runner =
-  timeout:int option -> steplimit:int option -> Why3Provers.t -> 'a ->
+  timeout:float option -> steplimit:int option -> Why3Provers.t -> 'a ->
   VCS.result Task.task
 
+val promote: ?timeout:float -> ?steplimit:int -> VCS.result -> VCS.result
+(** Converts some known results to the given limits.
+    In particular, if the result shall be discarded with respect to the limits,
+    the function returns [VCS.no_result]. *)
+
 val get_result: digest:('a digest) -> runner:('a runner) -> 'a runner
 val clear_result: digest:('a digest) -> Why3Provers.t -> 'a -> unit
 
diff --git a/src/plugins/wp/Changelog b/src/plugins/wp/Changelog
index 18db349af158e27999facca833c2c08da6111457..e5014c708ca44c9f13901cc81eb4f44c82067707 100644
--- a/src/plugins/wp/Changelog
+++ b/src/plugins/wp/Changelog
@@ -20,24 +20,46 @@
 #   <Prover>: prover
 ###############################################################################
 
-########################
+###############################################################################
 Plugin WP <next-release>
-########################
+###############################################################################
+
+- WP          [2023-06-05] Tactic Compute (new, generalize Definition and Split)
+- WP          [2023-06-05] Tactic Absurd now also applies to proof goal
+- WP          [2023-06-05] Option -wp-prop extended to lemma and function names
+- TIP         [2023-06-05] Activation of Strategies
+- WP          [2023-06-05] New option -wp-no-strategy-engine to deactivate strategies
+- WP          [2023-06-05] New option -wp-script=mode (see also -wp-cache-env)
+- WP          [2023-06-05] New option -wp-status to print unproved goals
+- WP          [2023-06-05] New option -wp-tactic to search for tactics
+- WP          [2023-06-05] New option -wp-strategy s,... for default strategies
+- WP          [2023-06-05] ACSL extension 'strategy' for proof strategies
+- WP          [2023-06-05] ACSL extension 'proof' for proof resolution hints
+
+###############################################################################
+Plugin WP 27.0 (Cobalt)
+###############################################################################
 
+- WP          [2023-05-03] new warning against unions (see -wp-warn-key "union")
+- WP          [2023-04-03] Default timeout set to 2s
+- WP          [2023-03-29] fix option -wp-split to only split conditions
+- WP          [2023-03-29] new option -wp-split-switch to split switches
+- WP          [2023-03-29] new option -wp-split-conj to split conjunctive goals
+- WP          [2023-03-29] renamed option -wp-split-depth into -wp-split-cnf
 - WP          [2023-03-14] Upgrade to Why3 1.6.0
 - WP          [2023-02-03] new option -wp-why3-extra-config for providing
                            additional Why3 configuration files
 
-#####################
+###############################################################################
 Plugin WP 26.1 (Iron)
-#####################
+###############################################################################
 
 - WP          [2022-12-02] Fixes 'terminates' goals generation when some
                            'terminates' or 'decreases' clauses are missing.
 
-#####################
+###############################################################################
 Plugin WP 26.0 (Iron)
-#####################
+###############################################################################
 
 - WP          [2022-10-14] 'calls' ACSL extension moved into the kernel;
                            option -wp-dynamic marked as obsolete
@@ -45,9 +67,9 @@ Plugin WP 26.0 (Iron)
 - Cmd         [2022-07-29] Improves the WP JSON report provided by
                            -wp-report-json
 
-##########################
+###############################################################################
 Plugin WP 25.0 (Manganese)
-##########################
+###############################################################################
 
 - WP          [2022-05-06] Upgrade to Why3 1.5
 - WP          [2022-02-28] New option -wp-fct-timeout, used to customize the
@@ -67,9 +89,9 @@ Plugin WP 25.0 (Manganese)
                            split conjunctions into multiple hypotheses.
 - WP          [2021-11-08] Removed legacy WP engine and option -wp-legacy
 
-#########################
+###############################################################################
 Plugin WP 24.0 (Chromium)
-#########################
+###############################################################################
 
 - WP          [2021-10-25] Removes -wp-overflows option (unsound)
 - WP          [2021-06-11] Adds an experimental support of "terminates" clauses.
@@ -85,15 +107,15 @@ Plugin WP 24.0 (Chromium)
                            option -wp-smoke-dead-assumes
 - TIP         [2021-05-31] Generalized Overflow tactic
 
-#########################
+###############################################################################
 Plugin WP 23.1 (Vanadium)
-#########################
+###############################################################################
 
 - WP          [2021-07-15] Fix a crash related to opaque structures memory typing
 
-#########################
+###############################################################################
 Plugin WP 23.0 (Vanadium)
-#########################
+###############################################################################
 
 - WP          [2021-03-01] Section « Limitation & Roadmap » added to the WP manual.
 - WP          [2021-03-01] New internal WP engine, fixing many issues related to
@@ -109,9 +131,9 @@ Plugin WP 23.0 (Vanadium)
 - TIP         [2020-11-05] New tactic: Induction
 - WP          [2020-11-04] Removed option -wp-bits (now always enabled)
 
-#########################
+###############################################################################
 Plugin WP 22.0 (Titanium)
-#########################
+###############################################################################
 
 - WP          [2020-10-14] New warning "pedantic-assigns". WP needs precise
                            'assigns ... \from ...' specification about out
@@ -132,16 +154,16 @@ Plugin WP 22.0 (Titanium)
 - WP          [2020-07-06] New option -wp-cache-print
 - WP          [2020-06-12] Supports the \initialized ACSL predicate
 
-#########################
+###############################################################################
 Plugin WP 21.1 (Scandium)
-#########################
+###############################################################################
 
 -*  WP        [2020-06-23] Fixes Coq region function
 -*  WP        [2020-06-23] Fixes MemTyped structure loader for wp-rte
 
-#########################
+###############################################################################
 Plugin WP 21.0 (Scandium)
-#########################
+###############################################################################
 
 - WP          [2020-04-10] Full support for Why3 IEEE float library
 - WP          [2020-04-10] Removed option -wp-check
@@ -171,9 +193,9 @@ Plugin WP 21.0 (Scandium)
 - TIP         [2018-02-20] Extends bitwise tactics to dis-equalities
 - WP          [2018-02-18] Additional lemmas about logical shift compositions
 
-##########################
+###############################################################################
 Plugin WP 20.0 (Calcium)
-##########################
+###############################################################################
 
 - TIP         [2019-09-17] Using all selected Why-3 provers for proof search
 - Gui         [2019-09-17] Updated panel for provers, models, cache, etc.
@@ -198,9 +220,9 @@ Plugin WP 20.0 (Calcium)
 o Qed         [2019-06-27] More secure API for quantifier management
 - Qed         [2019-05-09] Transform (some) boolean quantifications into variable assignments
 
-##########################
+###############################################################################
 Plugin WP 19.0 (Potassium)
-##########################
+###############################################################################
 
 - Wp          [2019-05-09] Fixes -wp-simplify-is-cint simplifier
 - Wp          [2019-04-26] Now requires -warn-invalid-bool
@@ -226,9 +248,9 @@ Plugin WP 19.0 (Potassium)
 - Qed         [2017-10-27] New simplifications for validity and ranges
 - TIP         [2017-10-27] New tacticals for validity and ranges
 
-######################
+###############################################################################
 Plugin WP 18.0 (Argon)
-######################
+###############################################################################
 
 -  Wp         [2018-10-25] Added support for ACSL \offset construct
 -  Wp         [2018-09-04] Option -wp-warn-separation changed into -wp-warn-memory-model
@@ -239,9 +261,9 @@ Plugin WP 18.0 (Argon)
 -  Qed        [2018-06-20] Added more simplifications for invertible functions
 -  TIP        [2018-06-07] Extends tactical 'Split' to distribution of qualitifiers
 
-##################################
+###############################################################################
 Plugin WP 17.0 (Chlorine-20180501)
-##################################
+###############################################################################
 
 -  WP         [2018-03-08] Add the missing ACSL math builtins (see manual)
 -  WP         [2018-02-12] Experimental support for _Bool range (-wp-bool-range)
@@ -266,9 +288,9 @@ Plugin WP 17.0 (Chlorine-20180501)
 -  Qed        [2017-10-27] New simplifications for validirt and ranges
 -  TIP        [2017-10-27] New tacticals for validity and ranges
 
-################################
+###############################################################################
 Plugin WP 16.0 (Sulfur-20171101)
-################################
+###############################################################################
 
 - WP          [2017-10-18] Support for LoopCurrent and LoopEntry
 - TIP         [2017-04-25] Options -wp-time-{extra|margin} for more stability
@@ -286,9 +308,9 @@ Plugin WP 16.0 (Sulfur-20171101)
 - WP          [2017-03-12] Reduction of equalities with logic functions
 - WP          [2017-03-12] More simplifications wrt integer domains
 
-####################################
+###############################################################################
 Plugin WP 15.0 (Phosphorus-20170501)
-####################################
+###############################################################################
 
 - Qed         [2017-12-13] Transforms some quantifications into let constructs
 -  WP         [2017-05-15] Extract inductive predicates as Inductive in Coq
@@ -314,9 +336,9 @@ Plugin WP 15.0 (Phosphorus-20170501)
 -  WP         [2016-11-17] Warn against access to volatile l-values
 -  WP         [2016-11-17] Fix volatile access (see -wp-no-volatile)
 
-#################################
+###############################################################################
 Plugin WP 14.0 (Silicon-20161101)
-#################################
+###############################################################################
 
 -  WP         [2016-04-08] Unified variable usage for all models
 -  WP         [2016-10-06] Simplification of arithmetics models
@@ -324,9 +346,9 @@ Plugin WP 14.0 (Silicon-20161101)
 -  WP         [2016-10-06] Use cint and cfloat models by default
 -  WP         [2016-10-06] Fix -wp-rte with respect to models and kernel options
 
-##################################
+###############################################################################
 Plugin WP 1.0 (Aluminium_20160502)
-##################################
+###############################################################################
 
 - Coq         [2016-03-30] Fixed bug #2214 (coq realbase)
 - WP	      [2016-03-29] Support for why3 0.87 (and ide)
@@ -344,9 +366,9 @@ Plugin WP 1.0 (Aluminium_20160502)
 - WP	      [2015-11-19] New options to set prover commands
 - Coq	      [2015-11-19] Support for Proof General 4.3
 
-##################################
+###############################################################################
 Plugin WP 0.9 (Magnesium_20151002)
-##################################
+###############################################################################
 
 - WP	      [2015-09-02] Added support for float-classification.
               (\is_NaN, \is_finite, \is_infinite, \is_plus_infinity, \is_minus_infinity).
@@ -393,9 +415,9 @@ Plugin WP 0.9 (Magnesium_20151002)
 - WP	      [2014-09-24] Now accept patterns in drivers.
 -* WP	      [2014-09-15] Fixed bug #1828 (separation of locals/formals/heap).
 
-###############################
+###############################################################################
 Plugin WP 0.8 (Sodium_20150201)
-###############################
+###############################################################################
 
 - WP          [2014-09-05] Drivers for min/max.
 - Typed       [2014-09-04] Simplification of assigns and separated.
@@ -407,9 +429,9 @@ Plugin WP 0.8 (Sodium_20150201)
 - Cmd         [2014-05-22] Added option -wp-filename-truncation to truncate
 	                   proof obligation filenames.
 
-#############################
+###############################################################################
 Plugin WP 0.8 (Neon_20140301)
-#############################
+###############################################################################
 
 - Gui	      [2014-01-30] Edition of current proof script (right-click).
 - Gui	      [2014-01-30] Consistent icons with status.
@@ -423,18 +445,18 @@ Plugin WP 0.8 (Neon_20140301)
 - WP          [2013-12-09] Clever assigns everything with formals and locals.
 - WP	      [2013-11-26] More type constraints in typed memory model.
 
-#################################
+###############################################################################
 Plugin WP 0.7 (Fluorine_20130501)
-#################################
+###############################################################################
 
 -* Typed      [2013-05-23] Better trigger generation for arrays with Alt-Ergo.
 -* Provers    [2013-05-23] Fixed various bugs with drivers and provers.
 -* WP         [2013-05-23] Fixed various bugs on floats.
 -* Typed      [2013-05-23] Fixed bug on address differences and offsets.
 
-#################################
+###############################################################################
 Plugin WP 0.7 (Fluorine_20130401)
-#################################
+###############################################################################
 
 -* Makefile   [2013-04-17] Fixed bug #1385 about ocamllex.opt.
 -! Cmd        [2013-04-15] Removed now useless options -wp-huge, -wp-dot,
@@ -456,9 +478,9 @@ Plugin WP 0.7 (Fluorine_20130401)
 -  WP         [2012-10-09] Drivers for linking ACSL symbols to external
 	      libs (-wp-driver).
 
-###############################
+###############################################################################
 Plugin WP 0.6 (Oxygen_20120901)
-###############################
+###############################################################################
 
 -  WP	      [2012-09-14] Experimental simplifier with new 'Typed' model
 	      (see manual).
@@ -479,9 +501,9 @@ o! WP	      [2012-09-05] Enhanced Ocaml API (see manual). Old bindings
 -  Cmd	      [2012-02-03] Extended support for external libraries:
 	      Options -wp-coq-lib, -wp-why-lib and now -wp-alt-ergo-lib.
 
-#################################
+###############################################################################
 Plugin WP 0.5 (Nitrogen_20111001)
-#################################
+###############################################################################
 
 +* Store      [2012-01-03] Adding guard for 'fresh' axiomatization in Store.
 +  WP	      [2011-12-23] Timing.
@@ -492,9 +514,9 @@ Plugin WP 0.5 (Nitrogen_20111001)
 	      See options -wp-include, -wp-tactic, -wp-coq-lib and -wp-why-lib.
 -  Cmd	      [2011-11-21] Adding support for multi-provers in command line.
 
-#################################
+###############################################################################
 Plugin WP 0.4 (Nitrogen_20111001)
-#################################
+###############################################################################
 
 -  WP         [2011-10-24] Further improvement for proof of assigns clauses.
 -  WP         [2011-10-14] A warning is now emitted for missing assigns clauses.
@@ -546,9 +568,9 @@ Plugin WP 0.4 (Nitrogen_20111001)
 -* Gui        [2011-04-15] Fixed bug on PO status (wrong PO identification).
 -* Gui        [2011-04-13] Fixed bug #711 (cyclic dependencies).
 
-###############################
+###############################################################################
 Plugin WP 0.3 (Carbon_20110201)
-###############################
+###############################################################################
 
 -* Coq        [2011-04-08] Fixed bug #740 for Coq on Windows.
 	      WP now uses directly coqtop -compile instead of coqc.
@@ -568,18 +590,18 @@ Plugin WP 0.3 (Carbon_20110201)
 -* Coq        [2011-01-04] Fixed bug #702 on Coq output with large integers.
 -* WP         [2011-03-10] Proof of requires of the main entry point (bug #675).
 
-###############################
+###############################################################################
 Plugin WP 0.2 (Carbon_20101202)
-###############################
+###############################################################################
 
 -* Coq        [2010-12-16] Fixed bug #639: no more compilation to shared
 	      directory.
 -  Gui        [2010-12-16] Accessibility of all provers from gui.
 
-###############################
+###############################################################################
 Plugin WP 0.1 (Carbon_20101201)
-###############################
+###############################################################################
 
 -  WP         [2010-12-06] New WP plugin.
 
-#############################
+###############################################################################
diff --git a/src/plugins/wp/Cvalues.ml b/src/plugins/wp/Cvalues.ml
index ff71b075302ba46fd5682cf37e513a29e6dcb467..bd6fb1e508851b437cc911cb88fea7ac58cfb288 100644
--- a/src/plugins/wp/Cvalues.ml
+++ b/src/plugins/wp/Cvalues.ml
@@ -127,7 +127,7 @@ and init_comp_value value ci =
   match ci.cfields with
   | None -> initialized_value_opaque_comp value ci
   | Some fields ->
-    let make f = Cfield (f, KInit), init_value value (object_of f.ftype) in
+    let make f = cfield ~kind:KInit f, init_value value (object_of f.ftype) in
     Lang.F.e_record (List.map make fields)
 
 let initialized_obj = init_value e_true
@@ -249,7 +249,7 @@ struct
            match c.cfields with
            | None -> Logic Lang.t_prop
            | Some fields ->
-             let value f = e_getfield (e_var s) (Lang.Cfield (f, KValue)) in
+             let value f = e_getfield (e_var s) (Lang.cfield f) in
              let def = p_all (fun f -> is_typ f.ftype (value f)) fields in
              Predicate(Def,def)
          in {
@@ -443,7 +443,7 @@ module EQCOMP = WpContext.Generator(Cil_datatype.Compinfo)
           | Some fields ->
             let def = p_all
                 (fun f ->
-                   let fd = Cfield (f, KValue) in
+                   let fd = cfield f in
                    !equal_rec (Ctypes.object_of f.ftype)
                      (e_getfield ra fd) (e_getfield rb fd))
                 fields
diff --git a/src/plugins/wp/Definitions.ml b/src/plugins/wp/Definitions.ml
index 9eb47df7d5599e95c15d5a9e1266577b7dacdd08..b0bdacd34142ed670c1c29679e9748331ff321f4 100644
--- a/src/plugins/wp/Definitions.ml
+++ b/src/plugins/wp/Definitions.ml
@@ -321,7 +321,7 @@ class virtual visitor main =
                 | Some (LTsum cs) ->
                   let cases = List.map
                       (fun c ->
-                         Lang.CTOR c ,
+                         Lang.ctor c ,
                          List.map self#vtau_of_ltype c.ctor_params
                       ) cs in
                   Qed.Engine.Tsum cases
@@ -340,7 +340,7 @@ class virtual visitor main =
                   (List.map
                      (fun f ->
                         let t = Lang.tau_of_ctype f.ftype in
-                        self#vtau t ; Cfield (f, KValue) , t
+                        self#vtau t ; cfield f , t
                      ))
                   r.cfields
               in self#on_comp r fts ;
@@ -358,7 +358,7 @@ class virtual visitor main =
                   (List.map
                      (fun f ->
                         let t = Lang.init_of_ctype f.ftype in
-                        self#vtau t ; Cfield (f, KInit) , t
+                        self#vtau t ; cfield ~kind:KInit f , t
                      ))
                   r.cfields
               in self#on_icomp r fts ;
@@ -462,8 +462,8 @@ class virtual visitor main =
         begin
           symbols <- DF.add f symbols ;
           match f with
-          | Model { m_source = Extern e  } -> self#vlibrary e.ext_library
-          | Model { m_source = Generated _ } | ACSL _ -> self#vlfun f
+          | FUN { m_source = Extern e  } -> self#vlibrary e.ext_library
+          | FUN { m_source = Generated _ } | ACSL _ -> self#vlfun f
           | CTOR c -> self#vadt (Lang.adt c.ctor_type)
         end
 
diff --git a/src/plugins/wp/Lang.ml b/src/plugins/wp/Lang.ml
index c647b8120caaeffa12eeb3b67b128ebb12683499..e136f5b7960e00efa2cff1568f989eeca8077b4b 100644
--- a/src/plugins/wp/Lang.ml
+++ b/src/plugins/wp/Lang.ml
@@ -225,10 +225,7 @@ let rec tau_of_ltype t =
   | Ltype _ as b when Logic_const.is_boolean_type b -> Logic.Bool
   | Ltype(lt,lts) -> atype lt (List.map tau_of_ltype lts)
 
-let tau_of_return l =
-  match l.l_type with
-  | None -> Logic.Prop
-  | Some t -> tau_of_ltype t
+let tau_of_return = function None -> Logic.Prop | Some t -> tau_of_ltype t
 
 (* -------------------------------------------------------------------------- *)
 (* --- Datatypes                                                          --- *)
@@ -311,10 +308,17 @@ let datatype ~library name =
   let m = new_extern ~link:name ~library ~debug:name in
   Mtype m
 
+
+let field_observers = ref []
+let field_observe fd = List.iter (fun k -> k fd) !field_observers ; fd
+let on_field f = field_observers := f :: !field_observers
+
+let cfield ?(kind=KValue) fd = field_observe @@ Cfield(fd,kind)
+
 let record ~link ~library fts =
   let m = new_extern ~link ~library ~debug:link in
   let r = { fields = [] } in
-  let fs = List.map (fun (f,t) -> Mfield(m,r,f,t)) fts in
+  let fs = List.map (fun (f,t) -> field_observe @@ Mfield(m,r,f,t)) fts in
   r.fields <- fs ; Mrecord(m,r)
 
 let field t f =
@@ -402,10 +406,10 @@ type lfun =
   (** Registered in Definition.t, only  *)
   | CTOR of Cil_types.logic_ctor_info
   (** Not registered in Definition.t, directly converted/printed *)
-  | Model of model
+  | FUN of lsymbol
   (** Generated or External function *)
 
-and model = {
+and lsymbol = {
   m_category : lfun category ;
   m_params : sort list ;
   m_result : sort ;
@@ -418,13 +422,21 @@ and source =
   | Generated of WpContext.context option * string
   | Extern of Engine.link extern
 
+let lfun_observers = ref []
+let lfun_observe lf = List.iter (fun k -> k lf) !lfun_observers ; lf
+let on_lfun f = lfun_observers := f :: !lfun_observers
+
+let acsl lf = lfun_observe (ACSL lf)
+let ctor cf = lfun_observe (CTOR cf)
+let lsymbol m = lfun_observe (FUN m)
+
 let tau_of_lfun phi ts =
   match phi with
-  | ACSL f -> tau_of_return f
+  | ACSL f -> tau_of_return f.l_type
   | CTOR c ->
     if c.ctor_type.lt_params = [] then Logic.Data(Atype c.ctor_type,[])
     else raise Not_found
-  | Model m -> match m.m_result with
+  | FUN m -> match m.m_result with
     | Sint -> Int
     | Sreal -> Real
     | Sbool -> Bool
@@ -432,7 +444,7 @@ let tau_of_lfun phi ts =
 
 let is_coloring_lfun = function
   | ACSL _ | CTOR _ -> false
-  | Model { m_coloring } -> m_coloring
+  | FUN { m_coloring } -> m_coloring
 
 type balance = Nary | Left | Right
 
@@ -481,7 +493,7 @@ let symbolf
          match result with Some t -> fun _ -> t | None -> not_found in
        let result =
          match result with Some t -> Kind.of_tau t | None -> sort in
-       Model {
+       lsymbol {
          m_category = category ;
          m_params = params ;
          m_result = result ;
@@ -509,7 +521,7 @@ let extern_p ~library ?bool ?prop ?link ?(params=[]) ?(coloring=false) () =
     | _ , _ , _ -> assert false
   in
   let debug = Export.debug link in
-  Model {
+  lsymbol {
     m_category = Logic.Function;
     m_params = params ;
     m_result = Logic.Sprop;
@@ -522,7 +534,7 @@ let extern_fp ~library ?(params=[]) ?link ?(coloring=false) phi =
   let link = match link with
     | None -> Engine.F_call phi
     | Some link -> Engine.F_call link in
-  Model {
+  lsymbol {
     m_category = Logic.Function ;
     m_params = params ;
     m_result = Logic.Sprop;
@@ -538,7 +550,7 @@ let generated_f ?context ?category ?params ?sort ?result ?coloring name =
   symbolf ?context ?category ?params ?sort ?result ?coloring name
 
 let generated_p ?context ?(coloring=false) name =
-  Model {
+  lsymbol {
     m_category = Logic.Function ;
     m_params = [] ;
     m_result = Logic.Sprop;
@@ -558,14 +570,14 @@ struct
   let debug = function
     | ACSL f -> logic_id f
     | CTOR c -> ctor_id c
-    | Model({m_source=Generated(_,n)}) -> n
-    | Model({m_source=Extern e})    -> e.ext_debug
+    | FUN({m_source=Generated(_,n)}) -> n
+    | FUN({m_source=Extern e})    -> e.ext_debug
 
   let hash = function
     | ACSL f -> Logic_info.hash f
     | CTOR c -> Logic_ctor_info.hash c
-    | Model({m_source=Generated(_,n)}) -> Datatype.String.hash n
-    | Model({m_source=Extern e})    -> e.ext_id
+    | FUN({m_source=Generated(_,n)}) -> Datatype.String.hash n
+    | FUN({m_source=Extern e})    -> e.ext_id
 
   let compare_context c1 c2 =
     match c1 , c2 with
@@ -587,9 +599,9 @@ struct
   let compare f g =
     if f==g then 0 else
       match f , g with
-      | Model {m_source=mf} , Model {m_source=mg} -> compare_source mf mg
-      | Model _ , _ -> (-1)
-      | _ , Model _ -> 1
+      | FUN {m_source=mf} , FUN {m_source=mg} -> compare_source mf mg
+      | FUN _ , _ -> (-1)
+      | _ , FUN _ -> 1
       | ACSL f , ACSL g -> Logic_info.compare f g
       | ACSL _ , _ -> (-1)
       | _ , ACSL _ -> 1
@@ -600,12 +612,12 @@ struct
   let pretty fmt f = Format.pp_print_string fmt (debug f)
 
   let category = function
-    | Model m -> m.m_category
+    | FUN m -> m.m_category
     | ACSL _ -> Logic.Function
     | CTOR _ -> Logic.Constructor
 
   let sort = function
-    | Model m -> m.m_result
+    | FUN m -> m.m_result
     | ACSL { l_type=None } -> Logic.Sprop
     | ACSL { l_type=Some t } -> sort_of_ltype t
     | CTOR _ -> Logic.Sdata
@@ -613,7 +625,7 @@ struct
   let parameters = ref (fun _ -> [])
 
   let params = function
-    | Model m -> m.m_params
+    | FUN m -> m.m_params
     | CTOR ct -> List.map sort_of_ltype ct.ctor_params
     | (ACSL _) as f -> !parameters f
 
@@ -642,15 +654,20 @@ class virtual idprinting =
     method link = function
       | ACSL f -> Engine.F_call (self#sanitize_fun (logic_id f))
       | CTOR c -> Engine.F_call (self#sanitize_fun (ctor_id c))
-      | Model({m_source=Generated(_,n)}) -> Engine.F_call (self#sanitize_fun n)
-      | Model({m_source=Extern e}) -> e.ext_link
+      | FUN({m_source=Generated(_,n)}) -> Engine.F_call (self#sanitize_fun n)
+      | FUN({m_source=Extern e}) -> e.ext_link
   end
 
 let name_of_lfun = function
   | ACSL f -> logic_id f
   | CTOR c -> ctor_id c
-  | Model({m_source=Generated(_,f)}) -> f
-  | Model({m_source=Extern e}) -> e.ext_debug
+  | FUN({m_source=Generated(_,f)}) -> f
+  | FUN({m_source=Extern e}) -> e.ext_debug
+
+let context_of_lfun = function
+  | ACSL _ | CTOR _
+  | FUN({m_source=Extern _}) -> None
+  | FUN({m_source=Generated(ctxt,_)}) -> ctxt
 
 let name_of_field = function
   | Mfield(_,_,f,_) -> f
diff --git a/src/plugins/wp/Lang.mli b/src/plugins/wp/Lang.mli
index f39c4ae1d6357125ed4d9ae14637a2295a07db0e..bdb9af7a61b4e6c6f276457c569557b77e7f8a46 100644
--- a/src/plugins/wp/Lang.mli
+++ b/src/plugins/wp/Lang.mli
@@ -63,21 +63,21 @@ and 'a extern = {
   ext_debug  : string; (** just for printing during debugging *)
 }
 and fields = { mutable fields : field list }
-and field =
+and field = private
   | Mfield of mdt * fields * string * tau
   | Cfield of fieldinfo * datakind
 and tau = (field,adt) Logic.datatype
 
 type t_builtin = E_mdt of mdt | E_poly of (tau list -> tau)
 
-type lfun =
+type lfun = private
   | ACSL of Cil_types.logic_info (** Registered in Definition.t,
                                      only  *)
   | CTOR of Cil_types.logic_ctor_info (** Not registered in Definition.t
                                           directly converted/printed *)
-  | Model of model (** *)
+  | FUN of lsymbol (** External or Generated logic symbol *)
 
-and model = {
+and lsymbol = {
   m_category : lfun category ;
   m_params : sort list ;
   m_result : sort ;
@@ -99,6 +99,7 @@ val record :
   link:string -> library:string -> (string * tau) list -> adt
 val comp : compinfo -> adt
 val comp_init : compinfo -> adt
+val cfield : ?kind:datakind -> fieldinfo -> field
 val field : adt -> string -> field
 val fields_of_adt : adt -> field list
 val fields_of_tau : tau -> field list
@@ -108,6 +109,12 @@ val adt : logic_type_info -> adt (** Must not be a builtin *)
 
 type balance = Nary | Left | Right
 
+val on_lfun : (lfun -> unit) -> unit
+val on_field : (field -> unit) -> unit
+
+val acsl : logic_info -> lfun
+val ctor : logic_ctor_info -> lfun
+
 val extern_s :
   library:library ->
   ?link:Engine.link ->
@@ -158,7 +165,7 @@ val extern_t:
 val tau_of_object : c_object -> tau
 val tau_of_ctype : typ -> tau
 val tau_of_ltype : logic_type -> tau
-val tau_of_return : logic_info -> tau
+val tau_of_return : logic_type option -> tau
 val tau_of_lfun : lfun -> tau option list -> tau
 val tau_of_field : field -> tau
 val tau_of_record : field -> tau
@@ -196,6 +203,8 @@ val parameters : (lfun -> sort list) -> unit
 
 val name_of_lfun : lfun -> string
 val name_of_field : field -> string
+val context_of_lfun : lfun -> WpContext.context option
+(** LFuns are unique by name and context *)
 
 val is_coloring_lfun : lfun -> bool
 
diff --git a/src/plugins/wp/Letify.ml b/src/plugins/wp/Letify.ml
index 1a23cd256d121a01b27b912b693a155a9da3de9a..a10eb79cfdbe2c303e8cc99cf505b4caf116a4f7 100644
--- a/src/plugins/wp/Letify.ml
+++ b/src/plugins/wp/Letify.ml
@@ -68,10 +68,10 @@ struct
   let frank = function
     | ACSL _ -> 0
     | CTOR _ -> 3
-    | Model { m_category = Function } -> 0
-    | Model { m_category = Injection } -> 1
-    | Model { m_category = Operator _ } -> 2
-    | Model { m_category = Constructor } -> 3
+    | FUN { m_category = Function } -> 0
+    | FUN { m_category = Injection } -> 1
+    | FUN { m_category = Operator _ } -> 2
+    | FUN { m_category = Constructor } -> 3
 
   let reduce env a b =
     if F.is_subterm a b then add_sigma env b a else
diff --git a/src/plugins/wp/LogicCompiler.ml b/src/plugins/wp/LogicCompiler.ml
index 72eaba5ea25c27e4a9b9932edd8aae31a049b090..10eb12ec3c36ea830b2ae1b37c2ec52ffda6d488 100644
--- a/src/plugins/wp/LogicCompiler.ml
+++ b/src/plugins/wp/LogicCompiler.ml
@@ -428,6 +428,7 @@ struct
   let occurs_ps x ps = List.exists (F.occursp x) ps
 
   let compile_step
+      (tres: logic_type option)
       (name:string)
       (types:string list)
       (profile:logic_var list)
@@ -435,10 +436,11 @@ struct
       (cc : env -> 'a -> 'b)
       (filter : 'b -> var -> bool)
       (data : 'a)
-    : var list * trigger list * pred list * 'b * sig_param list =
+    : tau * var list * trigger list * pred list * 'b * sig_param list =
     let frame = logic_frame name types in
     in_frame frame
       begin fun () ->
+        let tres = Lang.tau_of_return tres in
         let env,domain,sigv = profile_env Logic_var.Map.empty [] [] profile in
         let env = default_label env labels in
         let result = cc env data in
@@ -464,7 +466,7 @@ struct
                  (Sigma.domain sigma) acc)
             frame.labels (parp,sigp)
         in
-        parm , frame.triggers , domain , result , sigm
+        tres, parm , frame.triggers , domain , result , sigm
       end ()
 
   let cc_term : (env -> Cil_types.term -> term) ref
@@ -505,9 +507,9 @@ struct
 
   let compile_lemma cluster name ~kind types labels lemma =
     let qs,prop = strip_forall [] lemma in
-    let xs,tgs,domain,prop,_ =
+    let _,xs,tgs,domain,prop,_ =
       let cc_pred = pred `Positive in
-      compile_step name types qs labels cc_pred in_pred prop in
+      compile_step None name types qs labels cc_pred in_pred prop in
     let weak = Wp_parameters.WeakIntModel.get () in
     let lemma = if weak then prop else F.p_hyps domain prop in
     {
@@ -557,48 +559,55 @@ struct
   (* -------------------------------------------------------------------------- *)
 
   let compile_lbpure cluster l =
-    let lfun = ACSL l in
-    let tau = Lang.tau_of_return l in
-    let parp,sigp = Lang.local profile_sig l.l_profile in
-    let ldef = {
-      d_lfun = lfun ;
-      d_types = List.length l.l_tparams ;
-      d_params = parp ;
-      d_cluster = cluster ;
-      d_definition = Logic tau ;
-    } in
-    Definitions.update_symbol ldef ;
-    Signature.update l (SIG sigp) ;
-    parp,sigp
+    let frame = logic_frame l.l_var_info.lv_name l.l_tparams in
+    in_frame frame
+      begin fun () ->
+        let lfun = Lang.acsl l in
+        let tau = Lang.tau_of_return l.l_type in
+        let parp,sigp = Lang.local profile_sig l.l_profile in
+        let ldef = {
+          d_lfun = lfun ;
+          d_types = List.length l.l_tparams ;
+          d_params = parp ;
+          d_cluster = cluster ;
+          d_definition = Logic tau ;
+        } in
+        Definitions.update_symbol ldef ;
+        Signature.update l (SIG sigp) ;
+        parp,sigp
+      end ()
 
   (* -------------------------------------------------------------------------- *)
   (* --- Compiling Abstract Logic Function (in axiomatic with no reads)     --- *)
   (* -------------------------------------------------------------------------- *)
 
   let compile_lbnone cluster l vars =
-    let lfun = ACSL l in
-    let tau = Lang.tau_of_return l in
-    let parm,sigm = Lang.local (profile_mem l) vars in
-    let ldef = {
-      d_lfun = lfun ;
-      d_types = List.length l.l_tparams ;
-      d_params = parm ;
-      d_cluster = cluster ;
-      d_definition = Logic tau ;
-    } in
-    Definitions.define_symbol ldef ;
-    type_for_signature l ldef sigm ; SIG sigm
+    let frame = logic_frame l.l_var_info.lv_name l.l_tparams in
+    in_frame frame
+      begin fun () ->
+        let lfun = Lang.acsl l in
+        let tau = Lang.tau_of_return l.l_type in
+        let parm,sigm = Lang.local (profile_mem l) vars in
+        let ldef = {
+          d_lfun = lfun ;
+          d_types = List.length l.l_tparams ;
+          d_params = parm ;
+          d_cluster = cluster ;
+          d_definition = Logic tau ;
+        } in
+        Definitions.define_symbol ldef ;
+        type_for_signature l ldef sigm ; SIG sigm
+      end ()
 
   (* -------------------------------------------------------------------------- *)
   (* --- Compiling Logic Function with Reads                                --- *)
   (* -------------------------------------------------------------------------- *)
 
   let compile_lbreads cluster l ts =
-    let lfun = ACSL l in
+    let lfun = Lang.acsl l in
     let name = l.l_var_info.lv_name in
-    let tau = Lang.tau_of_return l in
-    let xs,_,_,(),s =
-      compile_step name l.l_tparams l.l_profile l.l_labels
+    let tau,xs,_,_,(),s =
+      compile_step l.l_type name l.l_tparams l.l_profile l.l_labels
         reads in_reads ts
     in
     let ldef = {
@@ -616,15 +625,16 @@ struct
   (* -------------------------------------------------------------------------- *)
 
   let compile_rec name l cc filter data =
+    let tau = l.l_type in
     let types = l.l_tparams in
     let profile = l.l_profile in
     let labels = l.l_labels in
-    let result = compile_step name types profile labels cc filter data in
+    let result = compile_step tau name types profile labels cc filter data in
     if LogicUsage.is_recursive l then
       begin
-        let (_,_,_,_,s) = result in
+        let (_,_,_,_,_,s) = result in
         Signature.update l (SIG s) ;
-        compile_step name types profile labels cc filter data
+        compile_step tau name types profile labels cc filter data
       end
     else result
 
@@ -634,13 +644,12 @@ struct
 
   let compile_lbterm cluster l t =
     let name = l.l_var_info.lv_name in
-    let tau = Lang.tau_of_return l in
-    let xs,_,_,r,s = compile_rec name l term in_term t in
+    let tau,xs,_,_,r,s = compile_rec name l term in_term t in
     match F.repr r with
     | Qed.Logic.Kint c -> CST c
     | _ ->
       let ldef = {
-        d_lfun = ACSL l ;
+        d_lfun = Lang.acsl l ;
         d_types = List.length l.l_tparams ;
         d_params = xs ;
         d_cluster = cluster ;
@@ -654,10 +663,10 @@ struct
   (* -------------------------------------------------------------------------- *)
 
   let compile_lbpred cluster l p =
-    let lfun = ACSL l in
+    let lfun = Lang.acsl l in
     let name = l.l_var_info.lv_name in
     let cc_pred = pred `Positive in
-    let xs,_,_,r,s = compile_rec name l cc_pred in_pred p in
+    let _,xs,_,_,r,s = compile_rec name l cc_pred in_pred p in
     let ldef = {
       d_lfun = lfun ;
       d_types = List.length l.l_tparams ;
@@ -690,9 +699,9 @@ struct
     (* Compile cases with default definition and collect used chunks *)
     let support = List.fold_left
         (fun support (case,labels,types,lemma) ->
-           let _,_,_,_,s =
+           let _,_,_,_,_,s =
              let cc_pred = pred `Positive in
-             compile_step case types [] labels cc_pred in_pred lemma in
+             compile_step l.l_type case types [] labels cc_pred in_pred lemma in
            let labels_used = LogicUsage.get_induction_labels l case in
            List.fold_left (heap_case labels_used) support s)
         Heap.Map.empty cases in
@@ -713,7 +722,7 @@ struct
              support (parp,sigp)
         ) () in
     (* Set global Signature *)
-    let lfun = ACSL l in
+    let lfun = Lang.acsl l in
     let ldef = {
       d_lfun = lfun ;
       d_types = List.length l.l_tparams ;
@@ -770,7 +779,7 @@ struct
               | { ctor_name = l_name ; ctor_params = ts } as const ->
                 let vs, cs = List.split (List.map term_constraint ts) in
                 let ts = List.map Lang.F.e_var vs in
-                let const = F.e_fun ~result:tau_lt (CTOR const) ts in
+                let const = F.e_fun ~result:tau_lt (Lang.ctor const) ts in
                 let is_lt = F.p_call lfun [const] in
                 {
                   l_name ;
@@ -918,7 +927,7 @@ struct
     | CST c -> e_zint c
     | SIG sparam ->
       let es = call_params env phi labels sparam parameters in
-      F.e_fun ~result (ACSL phi) es
+      F.e_fun ~result (Lang.acsl phi) es
 
   let call_pred env
       (phi:logic_info)
@@ -928,7 +937,7 @@ struct
     | CST _ -> assert false
     | SIG sparam ->
       let es = call_params env phi labels sparam parameters in
-      F.p_call (ACSL phi) es
+      F.p_call (Lang.acsl phi) es
 
   (* -------------------------------------------------------------------------- *)
   (* --- Variable Bindings                                                  --- *)
diff --git a/src/plugins/wp/LogicSemantics.ml b/src/plugins/wp/LogicSemantics.ml
index 5a97311dcea09458488de9cd8ed397b040c8960d..96baad2451d79132d57ae02a8a6182fc4bd6c0f4 100644
--- a/src/plugins/wp/LogicSemantics.ml
+++ b/src/plugins/wp/LogicSemantics.ml
@@ -130,7 +130,7 @@ struct
     | TNoOffset -> v
     | TModel _ -> Wp_parameters.not_yet_implemented "Model field"
     | TField(f,offset) ->
-      let v_f = L.map (fun r -> e_getfield r (Cfield (f, KValue))) v in
+      let v_f = L.map (fun r -> e_getfield r (cfield f)) v in
       access_offset env v_f offset
     | TIndex(k,offset) ->
       let rk = C.logic env k in
@@ -145,9 +145,10 @@ struct
     | TNoOffset -> v
     | TModel _ -> Wp_parameters.not_yet_implemented "Model field"
     | TField(f,offset) ->
-      let r_f = e_getfield r (Cfield (f, KValue)) in
+      let fd = cfield f in
+      let r_f = e_getfield r fd in
       let r_fv = update_offset env r_f offset v in
-      e_setfield r (Cfield (f, KValue)) r_fv
+      e_setfield r fd r_fv
     | TIndex(k,offset) ->
       let k = val_of_term env k in
       let r_kv = update_offset env (e_get r k) offset v in
@@ -692,7 +693,7 @@ struct
     | TDataCons(c,ts) ->
       let es = List.map (val_of_term env) ts in
       let r = match LogicBuiltins.ctor c with
-        | ACSLDEF -> e_fun (CTOR c) es
+        | ACSLDEF -> e_fun (Lang.ctor c) es
         | HACK phi -> phi es
         | LFUN f -> e_fun f es ~result:(Lang.tau_of_ltype t.term_type)
       in Vexp r
diff --git a/src/plugins/wp/MemLoader.ml b/src/plugins/wp/MemLoader.ml
index 2b1cbfa0dff61c0c971c1f64e87a0af94c7e3f8a..74ab9a5ba647851441dc579580eedcfcb6e1ae7a 100644
--- a/src/plugins/wp/MemLoader.ml
+++ b/src/plugins/wp/MemLoader.ml
@@ -277,7 +277,7 @@ struct
             | Some fields ->
               let def = List.map
                   (fun f ->
-                     Cfield (f, Info.kind) ,
+                     cfield ~kind:Info.kind f,
                      Info.load sigma (object_of f.ftype) (M.field loc f)
                   ) fields
               in
diff --git a/src/plugins/wp/MemMemory.ml b/src/plugins/wp/MemMemory.ml
index 75148e0b2ad8c622ce136f1fcd05b141b18c31d9..5db102a4dcf67d0e16f65c803bf4bfe2dc6084ee 100644
--- a/src/plugins/wp/MemMemory.ml
+++ b/src/plugins/wp/MemMemory.ml
@@ -462,3 +462,15 @@ let separated ~shift ~addrof ~sizeof s1 s2 =
   r_disjoint (range s1) (range s2)
 
 (* -------------------------------------------------------------------------- *)
+(* --- Unsupported Unions                                                 --- *)
+(* -------------------------------------------------------------------------- *)
+
+let wkey = Wp_parameters.register_warn_category "union"
+
+let unsupported_union (fd : Cil_types.fieldinfo) =
+  if not fd.fcomp.cstruct then
+    Wp_parameters.warning ~once:true ~wkey
+      "Accessing union fields with WP might be unsound.@\n\
+       Please refer to WP manual."
+
+(* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/wp/MemMemory.mli b/src/plugins/wp/MemMemory.mli
index a8ac29bfbbe5aa9fd5a57b8fdc28e3afbd4398d4..094cbb0bdc479fa0e6ced313eafc9449dccf740d 100644
--- a/src/plugins/wp/MemMemory.mli
+++ b/src/plugins/wp/MemMemory.mli
@@ -134,4 +134,8 @@ val included :
   sizeof:(Ctypes.c_object -> term) ->
   'a Sigs.rloc -> 'a Sigs.rloc -> pred
 
+(** {2 Unsupported Union Fields} *)
+
+val unsupported_union : Cil_types.fieldinfo -> unit
+
 (* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/wp/MemTyped.ml b/src/plugins/wp/MemTyped.ml
index 9766ce052c7ec692002da0e7dcd66121f3442c60..c9748c9f908676f3425372043beb8e2961829f91 100644
--- a/src/plugins/wp/MemTyped.ml
+++ b/src/plugins/wp/MemTyped.ml
@@ -425,7 +425,10 @@ module Shift = WpContext.Generator(Cobj)
         dfun.d_lfun
     end)
 
-let field l f = e_fun (ShiftField.get f) [l]
+let field l f =
+  MemMemory.unsupported_union f ;
+  e_fun (ShiftField.get f) [l]
+
 let shift l obj k = e_fun (Shift.get obj) [l;k]
 
 module LITERAL =
diff --git a/src/plugins/wp/MemVar.ml b/src/plugins/wp/MemVar.ml
index 168c67c9aa0278f6d6fd7378eec05b4ae8394184..4c35bd2787c830e28c7874dbaa7fa31f0b6e48cc 100644
--- a/src/plugins/wp/MemVar.ml
+++ b/src/plugins/wp/MemVar.ml
@@ -546,6 +546,9 @@ struct
     | CARR of MemoryContext.validity (* In-context array *)
     | HEAP (* In-heap variable *)
 
+  let is_heap_allocated = function
+    | CREF | CVAL -> false | HEAP | CTXT _ | CARR _ -> true
+
   type loc =
     | Ref of varinfo
     | Val of mem * varinfo * ofs list (* The varinfo has {i not} been contextualized yet *)
@@ -713,10 +716,13 @@ struct
   let pointer_loc p = Loc (M.pointer_loc p)
   let pointer_val l = M.pointer_val (mloc_of_loc l)
 
-  let field l f = match l with
+  let field l f =
+    match l with
     | Loc l -> Loc (M.field l f)
     | Ref x -> noref ~op:"field access to" x
-    | Val(m,x,ofs) -> Val(m,x,ofs @ [Field f])
+    | Val(m,x,ofs) ->
+      if not @@ is_heap_allocated m then MemMemory.unsupported_union f ;
+      Val(m,x,ofs @ [Field f])
 
   let rec ofs_shift obj k = function
     | [] -> [Shift(obj,k)]
@@ -765,7 +771,7 @@ struct
 
   let rec access_gen kind a = function
     | [] -> a
-    | Field f :: ofs -> access_gen kind (e_getfield a (Cfield (f, kind))) ofs
+    | Field f :: ofs -> access_gen kind (e_getfield a (cfield ~kind f)) ofs
     | Shift(_,k) :: ofs -> access_gen kind (e_get a k) ofs
 
   let access = access_gen KValue
@@ -774,7 +780,7 @@ struct
   let rec update_gen kind a ofs v = match ofs with
     | [] -> v
     | Field f :: ofs ->
-      let phi = Cfield (f, kind) in
+      let phi = cfield ~kind f in
       let a_f = F.e_getfield a phi in
       let a_f_v = update_gen kind a_f ofs v in
       F.e_setfield a phi a_f_v
@@ -901,9 +907,6 @@ struct
 
   exception ShiftMismatch
 
-  let is_heap_allocated = function
-    | CREF | CVAL -> false | HEAP | CTXT _ | CARR _ -> true
-
   let shift_mismatch l =
     Wp_parameters.fatal "Invalid shift : %a" pretty l
 
@@ -1209,7 +1212,7 @@ struct
     | TComp({ cfields = Some fields },_) ->
       F.p_all
         (fun fd ->
-           forall_pointers phi (e_getfield v (Cfield (fd, KValue))) fd.ftype)
+           forall_pointers phi (e_getfield v (cfield fd)) fd.ftype)
         fields
     | TArray(elt,_,_) ->
       let k = Lang.freshvar Qed.Logic.Int in
@@ -1319,14 +1322,14 @@ struct
       (*TODO: optimized version for terminal [Field _] and [Index _] *)
 
       | Field f :: ofs ->
-        let cf = Cfield (f, kind) in
+        let cf = cfield ~kind f in
         let af = e_getfield a cf in
         let bf = e_getfield b cf in
         let hs = assigned_path kind hs xs ys af bf ofs in
         List.fold_left
           (fun hs g ->
              if Fieldinfo.equal f g then hs else
-               let cg = Cfield (g, kind) in
+               let cg = cfield ~kind g in
                let ag = e_getfield a cg in
                let bg = e_getfield b cg in
                let eqg = p_forall ys (p_equal ag bg) in
diff --git a/src/plugins/wp/Pattern.ml b/src/plugins/wp/Pattern.ml
new file mode 100644
index 0000000000000000000000000000000000000000..469258d7681c616991c174738131752f7d2b7337
--- /dev/null
+++ b/src/plugins/wp/Pattern.ml
@@ -0,0 +1,767 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of WP plug-in of Frama-C.                           *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2023                                               *)
+(*    CEA (Commissariat a l'energie atomique et aux energies              *)
+(*         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 Logic_typing
+open Logic_ptree
+
+(* -------------------------------------------------------------------------- *)
+(* --- Pattern Engine                                                     --- *)
+(* -------------------------------------------------------------------------- *)
+
+type 'a loc = { loc : location ; value : 'a }
+
+type pvar = string loc
+type ast = node loc
+and node =
+  | Any
+  | Pany of ast list
+  | Pvar of pvar
+  | Named of pvar * ast
+  | Range of int * int
+  | Int of Integer.t
+  | Bool of bool
+  | String of string
+  | Assoc of assoc * ast list
+  | Binop of ast * binop * ast
+  | Call of string * ast list * bool (* trailing .. *)
+  | Times of Integer.t * ast
+  | List of ast list
+  | Field of ast * string
+  | Get of ast * ast
+  | Set of ast * ast * ast
+and assoc = [ `Add | `Mul | `Concat | `Land | `Lor | `Lxor ]
+and binop = [ `Div | `Mod | `Repeat | `Eq | `Lt | `Le | `Ne | `Lsl | `Lsr ]
+
+let self p =
+  let pattern,self = match p.value with
+    | Named(x,_) | Pvar x -> p , x
+    | _ ->
+      let x = { loc = p.loc ; value= "\\target" } in
+      { loc = p.loc ; value = Named(x,p) } , x
+  in
+  pattern , { loc = p.loc ; value = Pvar self }
+
+let unroll op = function
+  | { value = Assoc(f,xs) } when f = op -> xs
+  | e -> [e]
+
+let assoc op a b =
+  {
+    loc = fst a.loc, snd b.loc ;
+    value = Assoc(op,unroll op a @ unroll op b) ;
+  }
+
+let concat ~loc es =
+  let es = List.map (unroll `Concat) es in
+  { loc ; value = Assoc(`Concat, List.concat es) }
+
+module Vmap = Map.Make(String)
+
+type context = {
+  typing : typing_context ;
+  mutable value : bool ;
+  mutable pvars : pvar Vmap.t ;
+}
+
+type pattern = ast
+type value = ast
+
+(* -------------------------------------------------------------------------- *)
+(* --- Node Parsing                                                       --- *)
+(* -------------------------------------------------------------------------- *)
+
+let context typing = { typing ; value = false ; pvars = Vmap.empty }
+
+let pint ctxt ~loc a =
+  try int_of_string a
+  with _ -> ctxt.typing.error loc "Invalid int %S" a
+
+let pinteger ctxt ~loc a =
+  try Integer.of_string a
+  with _ -> ctxt.typing.error loc "Invalid integer %S" a
+
+let pvar ctxt ~loc x =
+  try Vmap.find x ctxt.pvars with Not_found ->
+    if ctxt.value then
+      ctxt.typing.error loc "Unknown pattern variable '%s'" x
+    else
+      let pv = { loc ; value = x } in
+      ctxt.pvars <- Vmap.add x pv ctxt.pvars ; pv
+
+let pbound ctxt p =
+  let loc = p.lexpr_loc in
+  match p.lexpr_node with
+  | PLconstant (IntConstant a) -> pint ctxt ~loc a
+  | _ -> ctxt.typing.error loc "Invalid bound (int expected)"
+
+let rec ptrail rps = function
+  | [] -> List.rev rps,false
+  | [{ lexpr_node = PLrange(None,None) }] -> List.rev rps,true
+  | p::ps -> ptrail (p::rps) ps
+
+let rec parse ctxt p =
+  let loc = p.lexpr_loc in
+  match p.lexpr_node with
+  | PLvar "_" when not ctxt.value -> { loc ; value = Any }
+  | PLvar x -> { loc ; value = Pvar (pvar ctxt ~loc x) }
+  | PLnamed(x,p) ->
+    let pv = pvar ctxt ~loc x in
+    let pn = parse ctxt p in
+    { loc ; value = Named(pv,pn) }
+  | PLtrue -> { loc ; value = Bool true }
+  | PLfalse -> { loc ; value = Bool false }
+  | PLconstant (IntConstant n) ->
+    { loc ; value = Int (pinteger ctxt ~loc n) }
+  | PLconstant (StringConstant s) ->
+    { loc ; value = String s }
+  | PLrange(Some a,Some b) when not ctxt.value ->
+    { loc ; value = Range(pbound ctxt a,pbound ctxt b) }
+  | PLapp("\\any",[],ps) when not ctxt.value ->
+    { loc ; value = Pany (List.map (parse ctxt) ps) }
+  | PLapp("\\concat",[],[]) -> { loc ; value = List [] }
+  | PLapp("\\concat",[],ps) -> concat ~loc @@ List.map (parse ctxt) ps
+  | PLapp("\\repeat",[],[p;q]) -> parse_binop ctxt ~loc `Repeat p q
+  | PLapp(lf,[],ps) ->
+    let ps,trail = if ctxt.value then ps,false else ptrail [] ps in
+    { loc ; value = Call(lf,List.map (parse ctxt) ps,trail) }
+  | PLunop(Uminus,a) ->
+    let a = parse ctxt a in
+    { loc = a.loc ; value = Times(Integer.minus_one,a) }
+  | PLunop(Ubw_not,a) ->
+    let a = parse ctxt a in
+    { loc = a.loc ; value = Call("lf:lnot",[a],false) }
+  | PLbinop(a,Bmul,b) ->
+    let a = parse ctxt a in
+    let b = parse ctxt b in
+    begin
+      match a.value with
+      | Int k -> { loc ; value = Times(k,b) }
+      | _ -> assoc `Mul a b
+    end
+  | PLbinop(a,Bsub,b) ->
+    let a = parse ctxt a in
+    let b = parse ctxt b in
+    let b = { loc = b.loc ; value = Times(Integer.minus_one,b) } in
+    assoc `Add a b
+  | PLbinop(a,Badd,b) -> assoc `Add (parse ctxt a) (parse ctxt b)
+  | PLbinop(a,Bbw_or,b) -> assoc `Lor (parse ctxt a) (parse ctxt b)
+  | PLbinop(a,Bbw_and,b) -> assoc `Land (parse ctxt a) (parse ctxt b)
+  | PLbinop(a,Bbw_xor,b) -> assoc `Lxor (parse ctxt a) (parse ctxt b)
+  | PLbinop(a,Bdiv,b) -> parse_binop ctxt ~loc `Div a b
+  | PLbinop(a,Bmod,b) -> parse_binop ctxt ~loc `Mod a b
+  | PLbinop(a,Blshift,b) -> parse_binop ctxt ~loc `Lsl a b
+  | PLbinop(a,Brshift,b) -> parse_binop ctxt ~loc `Lsr a b
+  | PLrel(a,Lt,b) -> parse_binop ctxt ~loc `Lt a b
+  | PLrel(a,Le,b) -> parse_binop ctxt ~loc `Le a b
+  | PLrel(a,Gt,b) -> parse_binop ctxt ~loc `Lt b a
+  | PLrel(a,Ge,b) -> parse_binop ctxt ~loc `Le b a
+  | PLrel(a,Eq,b) -> parse_binop ctxt ~loc `Eq a b
+  | PLrel(a,Neq,b) -> parse_binop ctxt ~loc `Ne a b
+  | PLempty -> { loc ; value = List [] }
+  | PLlist ps -> { loc ; value = List (List.map (parse ctxt) ps) }
+  | PLrepeat(p,n) -> parse_binop ctxt ~loc `Repeat p n
+  | PLdot(a,fd) -> { loc ; value = Field(parse ctxt a,fd) }
+  | PLarrget(a,b) ->
+    begin
+      match b.lexpr_node with
+      | PLarrget(k,v) ->
+        { loc ; value = Set(parse ctxt a,parse ctxt k,parse ctxt v) }
+      | _ ->
+        { loc ; value = Get(parse ctxt a,parse ctxt b) }
+    end
+  | _ ->
+    ctxt.typing.error loc
+      (if ctxt.value then "Invalid value" else "Invalid pattern")
+
+and parse_binop ctxt ~loc op a b =
+  { loc ; value = Binop(parse ctxt a,op,parse ctxt b) }
+
+let pa_pattern ctxt p = ctxt.value <- false ; parse ctxt p
+let pa_value ctxt p = ctxt.value <- true ; parse ctxt p
+
+(* -------------------------------------------------------------------------- *)
+(* --- Pretty                                                             --- *)
+(* -------------------------------------------------------------------------- *)
+
+let rec pp fmt (a : ast) =
+  match a.value with
+  | Any ->  Format.pp_print_string fmt "_"
+  | Pvar x -> Format.pp_print_string fmt x.value
+  | Named (x,v) -> Format.fprintf fmt "%s:%a" x.value pp v
+  | Range(a,b) -> Format.fprintf fmt "(%d..%d)" a b
+  | Int n -> Integer.pretty fmt n
+  | Bool b -> Format.pp_print_string fmt (if b then "\\true" else "\\false")
+  | String s -> Format.fprintf fmt "%S" s
+  | Assoc(`Land,[]) -> Format.pp_print_string fmt "-1"
+  | Assoc(`Mul,[]) -> Format.pp_print_string fmt "1"
+  | Assoc((`Add|`Lor|`Lxor),[]) -> Format.pp_print_string fmt "0"
+  | Assoc(`Concat,[]) -> Format.pp_print_string fmt "[| |]"
+  | Assoc(op,v::vs) ->
+    let op = match op with
+      | `Add -> '+'
+      | `Mul -> '*'
+      | `Concat | `Lxor -> '^'
+      | `Land -> '&'
+      | `Lor -> '|'
+    in
+    Format.fprintf fmt "@[<hov 2>(%a" pp v ;
+    List.iter (Format.fprintf fmt "@ %c %a" op pp) vs ;
+    Format.fprintf fmt ")@]"
+  | Binop(a,op,b) ->
+    let op = match op with
+      | `Div -> "/"
+      | `Mod -> "%"
+      | `Eq -> "=="
+      | `Ne -> "!="
+      | `Lt -> "<"
+      | `Le -> "<="
+      | `Repeat -> "*^"
+      | `Lsl -> "<<"
+      | `Lsr -> ">>"
+    in Format.fprintf fmt "@[<hov 2>(%a@ %s %a)@]" pp a op pp b
+  | Times(k,v) -> Format.fprintf fmt "%a*%a" Integer.pretty k pp v
+  | Get(a,k) -> Format.fprintf fmt "@[<hov 2>%a[@,%a]@]" pp a pp k
+  | Set(a,k,v) -> Format.fprintf fmt "@[<hov 2>%a[@,%a@ -> %a]@]" pp a pp k pp v
+  | List [] -> Format.pp_print_string fmt "[| |]"
+  | List (v::vs) ->
+    Format.fprintf fmt "@[<hov 2>[| %a" pp v ;
+    List.iter (Format.fprintf fmt " ;@ %a" pp) vs ;
+    Format.fprintf fmt " |]@]"
+  | Field(v,id) -> Format.fprintf fmt "%a.%s" pp v id
+  | Call(id,[],true) -> Format.fprintf fmt "%s(..)" id
+  | Call(id,[],false) -> Format.fprintf fmt "%s()" id
+  | Call(id,v::vs,trail) ->
+    Format.fprintf fmt "@[<hov 2>%s(%a" id pp v ;
+    List.iter (Format.fprintf fmt ",@ %a" pp) vs ;
+    if trail then Format.fprintf fmt ",@ .." ;
+    Format.fprintf fmt ")@]"
+  | Pany [] -> Format.pp_print_string fmt "\\never"
+  | Pany (v::vs) ->
+    Format.fprintf fmt "@[<hov 2>\\any(%a" pp v ;
+    List.iter (Format.fprintf fmt ",@ %a" pp) vs ;
+    Format.fprintf fmt ")@]"
+
+let pp_value = pp
+let pp_pattern = pp
+
+(* -------------------------------------------------------------------------- *)
+(* --- Pattern Matching                                                   --- *)
+(* -------------------------------------------------------------------------- *)
+
+type sigma = Tactical.selection Vmap.t
+
+type penv = {
+  mutable sigma : sigma ;
+  mutable marked : Lang.F.Tset.t ;
+  select : Lang.F.term -> Tactical.selection ;
+}
+
+let merge env (x : pvar) e =
+  try
+    let s = Vmap.find x.value env.sigma in
+    let v = Tactical.selected s in
+    if not (Lang.F.equal v e) then
+      raise Not_found
+  with Not_found ->
+    env.sigma <- Vmap.add x.value (env.select e) env.sigma
+
+let rec is_any (p : pattern) =
+  match p.value with
+  | Any | Pvar _ -> true
+  | Named(_,q) -> is_any q
+  | _ -> false
+
+let rec pmatch env (p : pattern) e =
+  match p.value , Lang.F.repr e with
+  | Any , _ -> ()
+  | Pvar x , _ -> merge env x e
+  | Named(x,p) , _ -> merge env x e ; pmatch env p e
+  | Range(a,b) , Kint n ->
+    begin
+      match Integer.to_int_opt n with
+      | Some v when a <= v && v <= b -> ()
+      | _ -> raise Not_found
+    end
+  | Bool true , True -> ()
+  | Bool false , False -> ()
+  | Assoc(`Add,ps) , Add es -> pac env Lang.F.e_sum [] ps es
+  | Assoc(`Mul,ps) , Mul es -> pac env Lang.F.e_prod [] ps es
+  | Assoc(`Lor,ps) , Fun(lf,es) when lf == Cint.f_lor ->
+    pac env (Lang.F.e_fun lf) [] ps es
+  | Assoc(`Land,ps) , Fun(lf,es) when lf == Cint.f_land ->
+    pac env (Lang.F.e_fun lf) [] ps es
+  | Assoc(`Lxor,ps) , Fun(lf,es) when lf == Cint.f_lxor ->
+    pac env (Lang.F.e_fun lf) [] ps es
+  | Binop(p,`Div,q) , Div(a,b) -> pbinop env p q a b
+  | Binop(p,`Eq,q) , Div(a,b) -> pbinop env p q a b
+  | Binop(p,`Ne,q) , Div(a,b) -> pbinop env p q a b
+  | Binop(p,`Lt,q) , Div(a,b) -> pbinop env p q a b
+  | Binop(p,`Le,q) , Div(a,b) -> pbinop env p q a b
+  | Binop(p,`Lsl,q) , Fun(lf,[a;b]) when lf == Cint.f_lsl -> pbinop env p q a b
+  | Binop(p,`Lsr,q) , Fun(lf,[a;b]) when lf == Cint.f_lsr -> pbinop env p q a b
+  | Times(b,p) , Times(a,e) ->
+    let q,r = Integer.c_div_rem a b in
+    if Integer.is_zero r then pmatch env p (Lang.F.e_times q e)
+    else raise Not_found
+  | Get(pa,pk) , Aget(a,k) ->
+    pmatch env pa a ; pmatch env pk k
+  | Set(pa,pk,pv) , Aset(a,k,v) ->
+    pmatch env pa a ; pmatch env pk k ; pmatch env pv v
+  | Field(pv,fid) , Rget(v,fd) when Lang.name_of_field fd = fid ->
+    pmatch env pv v
+  | Call(fid,ps,trail) , Fun(lf,es) when Lang.name_of_lfun lf = fid ->
+    begin
+      match Lang.Fun.category lf with
+      | Operator op ->
+        if op.associative then
+          let rps = if trail then [{ loc = p.loc ; value = Any }] else [] in
+          if op.commutative then
+            pac env (Lang.F.e_fun lf) rps ps es
+          else
+            passoc env (Lang.F.e_fun lf) rps ps [] es
+        else
+          pargs env ps trail es
+      | _ -> pargs env ps trail es
+    end
+  | Binop(pl,`Repeat,pn) , Fun(lf,[l;n]) when lf == Vlist.f_repeat ->
+    pmatch env pl l ; pmatch env pn n
+  | List _vs , _ -> ()
+  | Pany ps , _ ->
+    let ok = List.exists (fun p -> ptry env p e) ps in
+    if not ok then raise Not_found
+  | _ -> raise Not_found
+
+and pbinop env p q a b = pmatch env p a ; pmatch env q b
+
+(* Associative matching :
+   - rps are (reversed) any-patterns to be matched with (reversed) rvs values
+   - invariant is (rev rps @ ps) being matched with (rev rvs @ vs) *)
+and passoc env op rps ps rvs vs =
+  match ps with
+  | [] -> pany env op (List.rev rps) (List.rev_append rvs vs)
+  | p::ps ->
+    if is_any p then passoc env op (p::rps) ps rvs vs
+    else
+      match vs with
+      | [] -> raise Not_found
+      | v::vs ->
+        if ptry env p v then
+          begin
+            pany env op (List.rev rps) (List.rev rvs) ;
+            passoc env op [] ps [] vs
+          end
+        else
+          passoc env op rps ps (v::rvs) vs
+
+(* AC matching:
+   - rps are (reversed) any-patterns
+   - invariant is (rev rs @ ps) being matched with es *)
+and pac env op rps ps es =
+  match ps with
+  | p::ps ->
+    if is_any p then pac env op (p::rps) ps es
+    else
+      let ep = List.find (ptry env p) es in
+      let es = List.filter (fun e -> not @@ Lang.F.equal ep e) es in
+      pac env op rps ps es
+  | [] -> pany env op (List.rev rps) es
+
+(* Match with backtracking *)
+and ptry env p e =
+  let s0 = env.sigma in
+  try pmatch env p e ; true
+  with Not_found -> env.sigma <- s0 ; false
+
+(* Matching any-patterns rs with es *)
+and pany env op rs es =
+  match rs , es with
+  | [] , [] -> ()
+  | rs , [] ->
+    let e = op [] in
+    List.iter (fun r -> pmatch env r e) rs
+  | r::rs , e::es -> pmatch env r e ; pany env op rs es
+  | [] , _::_ -> raise Not_found
+
+(* Pairwise matching *)
+and pargs env ps trail es =
+  match ps , es with
+  | [] , [] -> ()
+  | [] , _ when trail -> ()
+  | p::ps , e::es -> pmatch env p e ; pargs env ps trail es
+  | _ -> raise Not_found
+
+(* Deep matching with marking *)
+let rec pchildren env p e =
+  let rs = ref [] in
+  Lang.F.lc_iter (fun e -> rs := e :: !rs) e ;
+  List.exists (pchild env p) (List.rev !rs)
+
+and pchild env p e =
+  if Lang.F.lc_closed e then
+    not (Lang.F.Tset.mem e env.marked) &&
+    begin
+      env.marked <- Lang.F.Tset.add e env.marked ;
+      ptry env p e || pchildren env p e
+    end
+  else
+    pchildren env p e
+
+let rec plist f =
+  function [] -> None | x::xs ->
+  match f x with
+  | Some _ as result -> result
+  | None -> plist f xs
+
+(* -------------------------------------------------------------------------- *)
+(* --- Pattern Lookup                                                     --- *)
+(* -------------------------------------------------------------------------- *)
+
+type lookup = {
+  head: bool ;
+  goal: bool ;
+  hyps: bool ;
+  pattern: pattern ;
+}
+
+let pclause { head ; pattern } clause sigma prop =
+  let tprop = Lang.F.e_prop prop in
+  let select t =
+    if t == tprop then Tactical.Clause clause else Tactical.Inside(clause,t) in
+  let env = { sigma ; select ; marked = Lang.F.Tset.empty } in
+  let pcond t =
+    if ptry env pattern t || (not head && pchildren env pattern t)
+    then Some env.sigma else None
+  in
+  match Lang.F.repr tprop with
+  | And ts -> plist pcond ts
+  | _ -> pcond tprop
+
+(* --- Step Ordering --- *)
+
+let queue = Queue.create ()
+
+let order (s : Conditions.step) : int =
+  match s.condition with
+  | Have _ -> 0
+  | When _ -> 1
+  | Branch _ -> 2
+  | Core _ -> 3
+  | Init _ -> 4
+  | Type _ -> 5
+  | Either _ -> 6
+  | State _ -> 7
+
+let priority sa sb = order sa - order sb
+
+let push (step : Conditions.step) =
+  match step.condition with
+  | Have _ | When _ | Core _ | Init _ | Type _ | State _ -> ()
+  | Branch(_,sa,sb) -> Queue.push sa queue ; Queue.push sb queue
+  | Either cs -> List.iter (fun s -> Queue.push s queue) cs
+
+(* --- Step Matching --- *)
+
+let pstep ctxt sigma (step : Conditions.step) =
+  let term = Conditions.head step in
+  let clause = Tactical.Step step in
+  pclause ctxt clause sigma term
+
+(* --- Sequence Matching --- *)
+
+let rec psequence ctxt sigma (seq : Conditions.sequence) =
+  let steps = List.sort priority (Conditions.list seq) in
+  match plist (pstep ctxt sigma) steps with
+  | Some _ as result ->
+    Queue.clear queue ; result
+  | None ->
+    List.iter push steps ;
+    if Queue.is_empty queue then None else
+      psequence ctxt sigma (Queue.pop queue)
+
+(* --- Hypotheses Matching --- *)
+
+let phyps ctxt sigma (seq : Conditions.sequent) =
+  if not ctxt.hyps then None else
+    psequence ctxt sigma (fst seq)
+
+let pgoal ctxt sigma (seq : Conditions.sequent) =
+  if not ctxt.goal then None else
+    let goal = snd seq in
+    let clause = Tactical.Goal goal in
+    pclause ctxt clause sigma goal
+
+let empty = Vmap.empty
+
+let psequent ctxt sigma (seq : Conditions.sequent) =
+  match pgoal ctxt sigma seq with
+  | Some _ as result -> result
+  | None -> phyps ctxt sigma seq
+
+(* -------------------------------------------------------------------------- *)
+(* --- Composing Values                                                   --- *)
+(* -------------------------------------------------------------------------- *)
+
+let () = Lang.on_lfun
+    begin fun lf ->
+      let id = "lf:" ^ Lang.name_of_lfun lf in
+      Tactical.add_computer id (Lang.F.e_fun lf)
+    end
+
+let () = Lang.on_field
+    begin fun fd ->
+      let id = "fd:" ^ Lang.name_of_field fd in
+      Tactical.add_computer id (fun es -> Lang.F.e_getfield (List.hd es) fd)
+    end
+
+let error ~loc msg =
+  Wp_parameters.logwith (fun _evt -> raise Not_found) ~source:(fst loc) msg
+
+let getvar env (x : string loc) : Tactical.selection =
+  try Vmap.find x.value env
+  with Not_found ->
+    error ~loc:x.loc "Pattern variable '%s' not bound" x.value
+
+let rec select (env : sigma) (a : value) =
+  let loc = a.loc in
+  let cc = select env in
+  match a.value with
+  | Any ->  error ~loc "Pattern _ is not a value"
+  | Pany _ ->  error ~loc "Pattern \\any(..) is not a value"
+  | String s -> error ~loc "String %S is not a value" s
+  | Pvar x -> getvar env x
+  | Named (_,v) -> cc v
+  | Range(a,b) -> Tactical.range a b
+  | Int n -> Tactical.cint n
+  | Bool b -> Tactical.compose (if b then "wp:true" else "wp:false") []
+  | Assoc(op,vs) ->
+    let op = match op with
+      | `Add -> "wp:add"
+      | `Mul -> "wp:mul"
+      | `Concat -> "wp:concat"
+      | `Lor -> "lf:lor"
+      | `Land -> "lf:land"
+      | `Lxor -> "lf:lxor"
+    in Tactical.compose op (List.map (cc) vs)
+  | Binop(a,op,b) ->
+    let op = match op with
+      | `Div -> "wp:div"
+      | `Mod -> "wp:mod"
+      | `Eq -> "wp:eq"
+      | `Ne -> "wp:neq"
+      | `Lt -> "wp:lt"
+      | `Le -> "wp:leq"
+      | `Repeat -> "wp:repeat"
+      | `Lsl -> "lf:lsl"
+      | `Lsr -> "lf:lsr"
+    in compose env ~loc op [a;b]
+  | Times(k,v) -> Tactical.compose "wp:mul" [Tactical.cint k;cc v]
+  | Get(a,k) -> Tactical.compose "wp:get" [cc a;cc k]
+  | Set(a,k,v) -> Tactical.compose "wp:set" [cc a;cc k;cc v]
+  | List vs -> Tactical.compose "wp:list" (List.map cc vs)
+  | Field(v,id) -> compose env ~loc ("fd:" ^ id) [v]
+  | Call(id,vs,_) -> compose env ~loc ("lf:" ^ id) vs
+
+and compose env ~loc id vs =
+  match Tactical.compose id (List.map (select env) vs) with
+  | Tactical.Empty -> error ~loc "Computer %S not found" id
+  | result -> result
+
+let bool (a : value) =
+  match a.value with
+  | Bool b -> b
+  | _ -> error ~loc:a.loc "Not a boolean value (%a)" pp a
+
+let string (a : value) =
+  match a.value with
+  | String s -> s
+  | _ -> error ~loc:a.loc "Not a string value (%a)" pp a
+
+(* -------------------------------------------------------------------------- *)
+(* --- Typechecking                                                       --- *)
+(* -------------------------------------------------------------------------- *)
+
+type vtype =
+  | Tnone | Tany | Numerical | Boolean | String
+  | List of vtype
+  | Array of vtype * vtype
+  | Type of Lang.F.tau
+
+let vint = Type Qed.Logic.Int
+let vbool = Type Qed.Logic.Bool
+let vlist = List Tany
+
+let list = function
+  | Type t -> Type (Vlist.alist t)
+  | Tnone -> Tnone
+  | v -> List v
+
+let array vk ve =
+  match vk , ve with
+  | Type tk, Type te -> Type (Qed.Logic.Array(tk,te))
+  | Tnone , _ | _ , Tnone -> Tnone
+  | _ -> Array(vk,ve)
+
+let rec vmerge va vb =
+  if va == vb then vb else
+    match va, vb with
+    | Tany , v | v, Tany -> v
+    (* numerical *)
+    | Numerical, Numerical -> Numerical
+    | Numerical, Type (Int | Real) -> vb
+    | Type (Int | Real), Numerical -> va
+    | Type Int , Type Real -> vb
+    | Type Real , Type Int -> va
+    (* boolean *)
+    | Boolean, Boolean -> Boolean
+    | Boolean, Type (Bool | Prop) -> vb
+    | Type (Bool | Prop) , Boolean -> va
+    | Type Bool , Type Prop -> vb
+    | Type Prop , Type Bool -> va
+    (* list *)
+    | List u , List v -> list (vmerge u v)
+    | (List m, Type t) | (Type t , List m) ->
+      begin
+        match Vlist.elist t with
+        | None -> Tnone
+        | Some te -> list (vmerge m (Type te))
+      end
+    (* arrays *)
+    | Array(vk,ve) , Array(uk,ue) ->
+      array (vmerge vk uk) (vmerge ve ue)
+    | (Array(vk,ve) , Type(Array(tk,te)))
+    | (Type(Array(tk,te)) , Array(vk,ve)) ->
+      array (vmerge vk (Type tk)) (vmerge ve (Type te))
+    (* types *)
+    | Type ta , Type tb -> if Lang.F.Tau.equal ta tb then vb else Tnone
+    | _ -> Tnone
+
+let rec vpretty fmt = function
+  | Tnone -> Format.fprintf fmt "\\none"
+  | Tany -> Format.fprintf fmt "\\any"
+  | List v -> Format.fprintf fmt "\\list(%a)" vpretty v
+  | Array(vk,ve) -> Format.fprintf fmt "%a[%a]" vpretty vk vpretty ve
+  | String -> Format.fprintf fmt "string"
+  | Numerical -> Format.fprintf fmt "number"
+  | Boolean -> Format.fprintf fmt "boolean"
+  | Type t -> Lang.F.Tau.pretty fmt t
+
+type env = vtype Vmap.t ref
+let env () = ref Vmap.empty
+
+let tc_merge ~loc va vb =
+  let v = vmerge va vb in
+  if v = Tnone then
+    Wp_parameters.error ~source:(fst loc) "Invalid type %a (expected %a)"
+      vpretty va vpretty vb ; v
+
+let tc_var env ~loc vt x =
+  let vx = try Vmap.find x !env with Not_found -> Tany in
+  let vy = tc_merge ~loc vt vx in
+  if vx != vy then env := Vmap.add x vy !env ; vy
+
+let rec typecheck env vt (a : ast) =
+  let loc = a.loc in
+  match a.value with
+  | Any -> vt
+  | Pany ps -> List.fold_left (typecheck env) vt ps
+  | Pvar x -> tc_var env ~loc vt x.value
+  | Named(x,v) -> tc_var env ~loc (typecheck env vt v) x.value
+  | Range(a,b) ->
+    if a > b then Wp_parameters.error ~source:(fst loc)
+        "Invalid range %d..%d" a b ;
+    tc_merge ~loc vt (Type Qed.Logic.Int)
+  | Int _ -> tc_merge ~loc vt vint
+  | Bool _ -> tc_merge ~loc vt vbool
+  | String _ -> tc_merge ~loc vt String
+  | Assoc((`Lor|`Land|`Lxor),vs) ->
+    List.fold_left (typecheck env) (tc_merge ~loc vint vt) vs
+  | Assoc((`Add|`Mul),vs) ->
+    List.fold_left (typecheck env) (tc_merge ~loc Numerical vt) vs
+  | Assoc(`Concat,vs) ->
+    List.fold_left (typecheck env) (tc_merge ~loc vlist vt) vs
+  | Binop(a,(`Eq | `Ne),b) ->
+    let va = typecheck env Tany a in
+    let vb = typecheck env Tany b in
+    ignore @@ tc_merge ~loc va vb ;
+    tc_merge ~loc vt Boolean
+  | Binop(a,(`Lt | `Le),b) ->
+    let va = typecheck env Numerical a in
+    let vb = typecheck env Numerical b in
+    ignore @@ tc_merge ~loc va vb ;
+    tc_merge ~loc vt Boolean
+  | Binop(a,`Div,b) ->
+    let vn = tc_merge ~loc Numerical vt in
+    let va = typecheck env vn a in
+    let vb = typecheck env vn b in
+    tc_merge ~loc va vb
+  | Binop(a,(`Mod|`Lsl|`Lsr),b) ->
+    ignore @@ typecheck env vint a ;
+    ignore @@ typecheck env vint b ;
+    tc_merge ~loc vt vint
+  | Binop(a,`Repeat,b) ->
+    ignore @@ typecheck env vint b ;
+    typecheck env (tc_merge ~loc vlist vt) a
+  | Times(_,v) -> typecheck env (tc_merge ~loc Numerical vt) v
+  | List vs ->
+    let ve = List.fold_left (typecheck env) Tany vs in
+    tc_merge ~loc vt (List ve)
+  | Get(a,k) ->
+    let vk = typecheck env Tany k in
+    begin
+      match typecheck env (Array(vk,vt)) a with
+      | Array(_,ve) -> ve
+      | Type(Array(_,te)) -> Type te
+      | va -> Wp_parameters.error ~source:(fst a.loc)
+                "Not an array type (%a)" vpretty va ; vt
+    end
+  | Set(a,k,v) ->
+    let vk = typecheck env Tany k in
+    let ve = typecheck env vt v in
+    typecheck env (array vk ve) a
+  | Field(v,fid) ->
+    begin
+      match typecheck env Tany v with
+      | Type(Record fds) ->
+        begin
+          try
+            let (_,ft) =
+              List.find (fun (fd,_) -> Lang.name_of_field fd = fid) fds in
+            tc_merge ~loc vt (Type ft)
+          with Not_found -> vt
+        end
+      | Tany -> vt
+      | vr -> Wp_parameters.error ~source:(fst v.loc)
+                "Not a record type (%a)" vpretty vr ; vt
+    end
+  | Call(_f,vs,_) ->
+    List.iter (fun v -> ignore @@ typecheck env Tany v) vs ; vt
+
+let typecheck_vtau env ?tau v =
+  ignore @@ typecheck env (match tau with None -> Tany | Some t -> Type t) v
+
+let typecheck_value = typecheck_vtau
+let typecheck_pattern = typecheck_vtau
+
+let typecheck_lookup env p =
+  ignore @@ typecheck env (if p.head then Boolean else Tany) p.pattern
+
+(* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/wp/Pattern.mli b/src/plugins/wp/Pattern.mli
new file mode 100644
index 0000000000000000000000000000000000000000..750fafc9e30234f1e2ff4d21852c5f5ae4516785
--- /dev/null
+++ b/src/plugins/wp/Pattern.mli
@@ -0,0 +1,86 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of WP plug-in of Frama-C.                           *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2023                                               *)
+(*    CEA (Commissariat a l'energie atomique et aux energies              *)
+(*         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 Logic_typing
+open Logic_ptree
+
+(* -------------------------------------------------------------------------- *)
+(* --- Pattern Engine                                                     --- *)
+(* -------------------------------------------------------------------------- *)
+
+type context
+type pattern
+type value
+
+(** Creates an empty environment *)
+val context : typing_context -> context
+
+(** Parse a pattern and enrich the environement with pattern variables *)
+val pa_pattern : context -> lexpr -> pattern
+
+(** Parse value according to the environement *)
+val pa_value : context -> lexpr -> value
+
+(** Return a value that equals the pattern *)
+val self : pattern -> pattern * value
+
+(** Pattern printer *)
+val pp_pattern : Format.formatter -> pattern -> unit
+
+(** Value printer *)
+val pp_value : Format.formatter -> value -> unit
+
+(** Matching lookup *)
+type lookup = {
+  head: bool ;
+  goal: bool ;
+  hyps: bool ;
+  pattern: pattern ;
+}
+
+(** Matching result *)
+type sigma
+
+(** Empty results *)
+val empty : sigma
+
+(** Matching sequent *)
+val psequent : lookup -> sigma -> Conditions.sequent -> sigma option
+
+(** Composing values from matching results *)
+val select : sigma -> value -> Tactical.selection
+
+(** Composing a boolean *)
+val bool : value -> bool
+
+(** Composing a string *)
+val string : value -> string
+
+(** Typechecking *)
+
+type env
+val env : unit -> env
+val typecheck_value : env -> ?tau:Lang.F.tau -> value -> unit
+val typecheck_pattern : env -> ?tau:Lang.F.tau -> pattern -> unit
+val typecheck_lookup : env -> lookup -> unit
+
+(* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/wp/ProofEngine.ml b/src/plugins/wp/ProofEngine.ml
index b8c5854a739645e686cf7a00456dcb174a65088e..9c96cffeb933d00724f249fe6dcf618b91faa4f4 100644
--- a/src/plugins/wp/ProofEngine.ml
+++ b/src/plugins/wp/ProofEngine.ml
@@ -30,6 +30,7 @@ type node = {
   parent : node option ;
   mutable script : script ;
   mutable stats : Stats.stats ;
+  mutable strategy : string option ; (* hint *)
   mutable search_index : int ;
   mutable search_space : Strategy.t array ; (* sorted by priority *)
 }
@@ -107,6 +108,7 @@ let proof ~main =
 let rec reset_node n =
   Wpo.clear_results n.goal ;
   if Wpo.is_tactic n.goal then Wpo.remove n.goal ;
+  n.strategy <- None ;
   match n.script with
   | Opened | Script _ -> ()
   | Tactic(_,children) ->
@@ -146,6 +148,11 @@ let iteri f tree =
     let k = ref 0 in
     walk (fun node -> f !k node ; incr k) r
 
+let rec depth node =
+  match node.parent with
+  | None -> 0
+  | Some p -> succ @@ depth p
+
 (* -------------------------------------------------------------------------- *)
 (* --- Consolidating                                                      --- *)
 (* -------------------------------------------------------------------------- *)
@@ -193,7 +200,8 @@ let consolidated wpo =
 (* -------------------------------------------------------------------------- *)
 
 let main t = t.main
-let head t = match t.head with
+let head t = t.head
+let head_goal t = match t.head with
   | None -> t.main
   | Some n -> n.goal
 let tree n = proof ~main:n.tree
@@ -335,6 +343,7 @@ let mk_tree_node ~tree ~anchor goal = {
   stats = Stats.empty ;
   search_index = 0 ;
   search_space = [| |] ;
+  strategy = None ;
 }
 
 let mk_root_node goal = {
@@ -342,6 +351,7 @@ let mk_root_node goal = {
   parent = None ;
   script = Opened ;
   stats = Stats.empty ;
+  strategy = None ;
   search_index = 0 ;
   search_space = [| |] ;
 }
@@ -452,4 +462,7 @@ let bound node =
   | Tactic _ | Opened -> []
   | Script s -> s
 
+let get_hint node = node.strategy
+let set_hint node strategy = node.strategy <- Some strategy
+
 (* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/wp/ProofEngine.mli b/src/plugins/wp/ProofEngine.mli
index 4e0cd3d9f627b3ce66fa7b8174633baae4d523d6..5fdb346c81be8070ef5fb335450a5a36d9c04788 100644
--- a/src/plugins/wp/ProofEngine.mli
+++ b/src/plugins/wp/ProofEngine.mli
@@ -72,9 +72,10 @@ val current : tree -> current
 val goto : tree -> position -> unit
 val root : tree -> node
 val main : tree -> Wpo.t
-val head : tree -> Wpo.t
-val tree : node -> tree
 val goal : node -> Wpo.t
+val tree : node -> tree
+val head : tree -> node option
+val head_goal : tree -> Wpo.t
 val tree_context : tree -> WpContext.t
 val node_context : node -> WpContext.t
 
@@ -83,10 +84,14 @@ val proved : node -> bool
 val pending : node -> int
 val stats : node -> Stats.stats
 val parent : node -> node option
+val depth : node -> int
 val children : node -> (string * node) list
 val tactical : node -> ProofScript.jtactic option
 val get_strategies : node -> int * Strategy.t array (* current index *)
 val set_strategies : node -> ?index:int -> Strategy.t array -> unit
+val get_hint : node -> string option
+val set_hint : node -> string -> unit
+
 val forward : tree -> unit
 val cancel : tree -> unit
 val remove : tree -> node -> unit
diff --git a/src/plugins/wp/ProofScript.ml b/src/plugins/wp/ProofScript.ml
index dfb26837dc05d9782e81d8f885c6bb9f75a52920..a654b1f42123ab5f1fd26f30cb158de1e4e75766 100644
--- a/src/plugins/wp/ProofScript.ml
+++ b/src/plugins/wp/ProofScript.ml
@@ -278,24 +278,32 @@ type jtactic = {
   tactic : string ;
   params : Json.t ;
   select : Json.t ;
+  strategy : string option ;
 }
 
-let jtactic ~title (tac : tactical) (sel : selection) =
+let jtactic ?strategy (tac : tactical) (sel : selection) =
   {
-    header = title ;
+    header = tac#title ;
     tactic = tac#id ;
     params = json_of_parameters tac ;
     select = json_of_selection sel ;
+    strategy ;
   }
 
 let json_of_tactic t js =
-  `Assoc [
+  let strategy =
+    match t.strategy with
+    | None -> []
+    | Some s -> [ "strategy" , `String s ]
+  in
+  let tactical = [
     "header" , `String t.header ;
     "tactic" , `String t.tactic ;
     "params" , t.params ;
     "select" , t.select ;
     "children" , `Assoc js ;
-  ]
+  ] in
+  `Assoc (strategy @ tactical)
 
 let children_of_json = function
   | `List js ->
@@ -311,8 +319,11 @@ let tactic_of_json js =
     let tactic = js >? "tactic" |> Json.string in
     let params = try js >? "params" with Not_found -> `Null in
     let select = try js >? "select" with Not_found -> `Null in
-    let children = try js >? "children" |> children_of_json with Not_found -> [] in
-    Some( { header ; tactic ; params ; select } , children )
+    let children =
+      try js >? "children" |> children_of_json with Not_found -> [] in
+    let strategy =
+      try Some (js >? "strategy" |> Json.string) with Not_found -> None in
+    Some( { header ; tactic ; params ; select ; strategy } , children )
   with _ -> None
 
 (* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/wp/ProofScript.mli b/src/plugins/wp/ProofScript.mli
index 7d4d3400347a0e12f15edfa682b0893479138d38..7c4ab83e58fbdbcf8b0eb7b7b24eea9f8a659846 100644
--- a/src/plugins/wp/ProofScript.mli
+++ b/src/plugins/wp/ProofScript.mli
@@ -35,6 +35,7 @@ and jtactic = {
   tactic : string ;
   params : Json.t ;
   select : Json.t ;
+  strategy : string option ;
 }
 
 val is_prover : alternative -> bool
@@ -54,7 +55,7 @@ val has_proof : jscript -> bool
 val decode : Json.t -> jscript
 val encode : jscript -> Json.t
 
-val jtactic : title:string -> tactical -> selection -> jtactic
+val jtactic : ?strategy:string -> tactical -> selection -> jtactic
 val configure : jtactic -> sequent -> (tactical * selection) option
 
 (** Json Codecs *)
diff --git a/src/plugins/wp/ProofSession.ml b/src/plugins/wp/ProofSession.ml
index 4e3e2eeaf3ac29456fa6a1f6bb91eb568becf1cb..678d280f5526a597d43ead2e0f096c8e6741e782 100644
--- a/src/plugins/wp/ProofSession.ml
+++ b/src/plugins/wp/ProofSession.ml
@@ -27,6 +27,58 @@ type script =
   | Script of string
   | Deprecated of string
 
+type mode =
+  | Batch
+  | Update
+  | Dry
+  | Init
+
+let parse_mode ~origin ~fallback = function
+  | "batch" -> Batch
+  | "update" -> Update
+  | "dry" -> Dry
+  | "init" -> Init
+  | "" -> raise Not_found
+  | m ->
+    Wp_parameters.warning ~current:false
+      "Unknown %s mode %S (use %s instead)" origin m fallback ;
+    raise Not_found
+
+module MODE = WpContext.StaticGenerator(Datatype.Unit)
+    (struct
+      type key = unit
+      type data = mode
+      let name = "Wp.Script.mode"
+      let compile () =
+        try
+          if not (Wp_parameters.CacheEnv.get()) then
+            raise Not_found ;
+          let origin = "FRAMAC_WP_SCRIPT" in
+          parse_mode ~origin ~fallback:"-wp-script" (Sys.getenv origin)
+        with Not_found ->
+        try
+          let mode = Wp_parameters.ScriptMode.get() in
+          parse_mode ~origin:"-wp-script" ~fallback:"batch" mode
+        with Not_found ->
+          let provers = Wp_parameters.Provers.get () in
+          if List.mem "tip" provers then Update else
+          if List.mem "script" provers then Batch else
+            Dry
+    end)
+
+let get_mode = MODE.get
+let set_mode m = MODE.set () m
+
+let scratch_mode () =
+  match MODE.get () with
+  | Batch | Update -> false
+  | Dry | Init -> true
+
+let saving_mode () =
+  match MODE.get () with
+  | Update | Init -> true
+  | Batch | Dry -> false
+
 let files : (string,script) Hashtbl.t = Hashtbl.create 32
 
 let jsonfile (dir:Datatype.Filepath.t) =
diff --git a/src/plugins/wp/ProofSession.mli b/src/plugins/wp/ProofSession.mli
index a7dd99a46ca7810fd7a155c4883eb8ab856529d8..833cfea103855fca7dbd6d7feddc24a050b5dffb 100644
--- a/src/plugins/wp/ProofSession.mli
+++ b/src/plugins/wp/ProofSession.mli
@@ -25,6 +25,18 @@ type script =
   | Script of string
   | Deprecated of string
 
+type mode =
+  | Batch
+  | Update
+  | Dry
+  | Init
+
+val get_mode : unit -> mode
+val set_mode : mode -> unit
+
+val scratch_mode : unit -> bool
+val saving_mode : unit -> bool
+
 val pp_file : Format.formatter -> string -> unit
 val pp_script_for : Format.formatter -> Wpo.t -> unit
 
diff --git a/src/plugins/wp/ProofStrategy.ml b/src/plugins/wp/ProofStrategy.ml
new file mode 100644
index 0000000000000000000000000000000000000000..4440b768d7be65fc0ac0278face838658303715e
--- /dev/null
+++ b/src/plugins/wp/ProofStrategy.ml
@@ -0,0 +1,600 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of WP plug-in of Frama-C.                           *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2023                                               *)
+(*    CEA (Commissariat a l'energie atomique et aux energies              *)
+(*         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
+open Logic_typing
+open Logic_ptree
+open Pattern
+module D = Datatype
+
+(* -------------------------------------------------------------------------- *)
+(* --- Proof Strategy Engine                                              --- *)
+(* -------------------------------------------------------------------------- *)
+
+type 'a loc = { loc : location ; value : 'a }
+
+(* Abstract Syntax Tree: must be stdlib-marshallable *)
+type strategy = {
+  name: string loc ;
+  alternatives: alternative list ;
+}
+
+and alternative =
+  | Default
+  | Strategy of string loc
+  | Provers of string loc list * float option (* timeout *)
+  | Auto of string loc (* deprecated -wp-auto *)
+  | Tactic of {
+      tactic : string loc ;
+      lookup : lookup list ;
+      select : value list ;
+      params : (string loc * value) list ;
+      children : (string loc * string loc) list ; (* name prefix and strategy *)
+      default: string loc option; (* None is default *)
+    }
+
+type hint = string * string list (* strategy name, targets *)
+
+(* -------------------------------------------------------------------------- *)
+(* --- Registry                                                           --- *)
+(* -------------------------------------------------------------------------- *)
+
+(* Strategies applies to all projects *)
+
+let kid = ref 0
+let hid : (int,hint) Hashtbl.t = Hashtbl.create 0
+let sid : (int,strategy) Hashtbl.t = Hashtbl.create 0
+let strategies : (string,strategy) Hashtbl.t = Hashtbl.create 0
+let revhints : hint list ref = ref []
+
+(* -------------------------------------------------------------------------- *)
+(* --- Printers                                                           --- *)
+(* -------------------------------------------------------------------------- *)
+
+let pp_name fmt { value = s } = Format.pp_print_string fmt s
+let pp_quoted fmt { value = s } = Format.fprintf fmt "%S" s
+
+let pp_lookup fmt = function
+  | { head = true ; goal = true ; hyps = false ; pattern } ->
+    Format.fprintf fmt "\\goal(%a)" Pattern.pp_pattern pattern
+  | { head = true ; goal = false ; pattern } ->
+    Format.fprintf fmt "\\when(%a)" Pattern.pp_pattern pattern
+  | { head = false ; goal = true ; hyps = false ; pattern } ->
+    Format.fprintf fmt "\\ingoal(%a)" Pattern.pp_pattern pattern
+  | { head = false ; goal = false ; pattern } ->
+    Format.fprintf fmt "\\incontext(%a)" Pattern.pp_pattern pattern
+  | { goal = true ; hyps = true ; pattern } ->
+    Format.fprintf fmt "\\pattern(%a)" Pattern.pp_pattern pattern
+
+let pp_select fmt s =
+  Format.fprintf fmt "\\select(%a)" Pattern.pp_value s
+
+let pp_param fmt (p,v) =
+  Format.fprintf fmt "\\param(%a,%a)" pp_quoted p Pattern.pp_value v
+
+let pp_child fmt (p,s) =
+  Format.fprintf fmt "\\child(%a,%a)" pp_quoted p pp_name s
+
+let pp_children fmt s =
+  Format.fprintf fmt "\\children(%a)" pp_name s
+
+let pp_alternative fmt = function
+  | Default -> Format.fprintf fmt "\\default"
+  | Strategy s -> pp_name fmt s
+  | Auto { value = s } -> Format.fprintf fmt "\\auto(%S)" s
+  | Provers([],None) -> Format.fprintf fmt "\\prover()"
+  | Provers([],Some tm) -> Format.fprintf fmt "\\prover(%.1f)" tm
+  | Provers(p::ps,None) ->
+    Format.fprintf fmt "@[<hov 2>\\prover(%a" pp_quoted p ;
+    List.iter (Format.fprintf fmt ",@,%a" pp_quoted) ps ;
+    Format.fprintf fmt ")@]" ;
+  | Provers(ps,Some tm) ->
+    Format.fprintf fmt "@[<hov 2>\\prover(" ;
+    List.iter (Format.fprintf fmt "%a,@," pp_quoted) ps ;
+    Format.fprintf fmt "%.1f)@]" tm ;
+  | Tactic { tactic ; lookup ; select ; params ; children ; default } ->
+    Format.fprintf fmt "@[<hv 2>\\tactic(%a" pp_quoted tactic ;
+    List.iter (Format.fprintf fmt ",@ %a" pp_lookup) lookup ;
+    List.iter (Format.fprintf fmt ",@ %a" pp_select) select ;
+    List.iter (Format.fprintf fmt ",@ %a" pp_param) params ;
+    List.iter (Format.fprintf fmt ",@ %a" pp_child) children ;
+    Option.iter (Format.fprintf fmt ",@ %a" pp_children) default ;
+    Format.fprintf fmt "@,)@]"
+
+let pp_strategy fmt s =
+  Format.fprintf fmt "%s:@ " s.name.value ;
+  Pretty_utils.pp_list ~sep:",@ " pp_alternative fmt s.alternatives
+
+let re_ident = Str.regexp "[_a-zA-Z][_a-zA-Z0-9]*$"
+
+let pp_option fmt s =
+  if Str.string_match re_ident s 0 then
+    Format.pp_print_string fmt s
+  else
+    Format.fprintf fmt "%S" s
+
+let pp_hint fmt ((s,ps): hint) =
+  Format.fprintf fmt "%s:@ " s ;
+  Pretty_utils.pp_list ~sep:",@ " pp_option fmt ps
+
+(* -------------------------------------------------------------------------- *)
+(* --- Alternative Parser                                                 --- *)
+(* -------------------------------------------------------------------------- *)
+
+let debug fmt p =
+  Format.fprintf fmt "@[<hov 2>at: %a@]" Logic_print.print_lexpr p
+
+let rec parse_provers ctxt provers timeout = function
+  | [] -> List.rev provers,timeout
+  | p::ps ->
+    let loc = p.lexpr_loc in
+    match p.lexpr_node with
+    | PLconstant (IntConstant t) ->
+      let time = try int_of_string t with Invalid_argument _ ->
+        ctxt.error loc "Invalid timeout" in
+      if time < 0 then ctxt.error loc "Invalid timeout" ;
+      if timeout <> None then ctxt.error loc "Duplicate timeout" ;
+      parse_provers ctxt provers (Some (float time)) ps
+    | PLconstant (FloatConstant t) ->
+      let time = try float_of_string t with Invalid_argument _ ->
+        ctxt.error loc "Invalid timeout" in
+      if time < 0.0 then ctxt.error loc "Invalid timeout" ;
+      if timeout <> None then ctxt.error loc "Duplicate timeout" ;
+      parse_provers ctxt provers (Some time) ps
+    | PLconstant (StringConstant value) ->
+      parse_provers ctxt ( { loc ; value } :: provers ) timeout ps
+    | _ -> ctxt.error loc "Invalid prover specification (%a)" debug p
+
+let parse_name ctxt ~kind ?check p =
+  let loc = p.lexpr_loc in
+  match p.lexpr_node with
+  | PLvar value
+  | PLapp(value,[],[])
+  | PLconstant(StringConstant value)
+    ->
+    Option.iter (fun f -> f loc value) check ;
+    { loc ; value }
+  | _ -> ctxt.error loc "%s name expected (%a)" kind debug p
+
+let parse_lookup penv ?(head=true) ?(goal=false) ?(hyps=false) p =
+  { goal ; hyps ; head ; pattern = Pattern.pa_pattern penv p }
+
+let autoselect select lookup =
+  match select , lookup with
+  | [] , p::ps ->
+    let q,v = Pattern.self p.pattern in
+    [v] , { p with pattern = q }::ps
+  | _ -> select, lookup
+
+let rec parse_tactic_params ctxt penv
+    ~tactic ~select ~lookup ~params ~children ~default ps =
+  match ps with
+  | [] ->
+    let select = List.rev select in
+    let lookup = List.rev lookup in
+    let select,lookup = autoselect select lookup in
+    Tactic {
+      tactic ; select ; lookup ;
+      params = List.rev params ;
+      children = List.rev children ;
+      default ;
+    }
+  | p::ps ->
+    let loc = p.lexpr_loc in
+    let cc = parse_tactic_params ctxt penv ~tactic in
+    match p.lexpr_node with
+    | PLapp("\\goal",[],qs) ->
+      let qs = List.map (parse_lookup ~goal:true penv) qs in
+      let lookup = List.rev_append qs lookup in
+      cc ~select ~lookup ~params ~children ~default ps
+    | PLapp("\\when",[],qs) ->
+      let qs = List.map (parse_lookup ~hyps:true penv) qs in
+      let lookup = List.rev_append qs lookup in
+      cc ~select ~lookup ~params ~children ~default ps
+    | PLapp("\\ingoal",[],qs) ->
+      let qs = List.map (parse_lookup ~head:false ~goal:true penv) qs in
+      let lookup = List.rev_append qs lookup in
+      cc ~select ~lookup ~params ~children ~default ps
+    | PLapp("\\incontext",[],qs) ->
+      let qs = List.map (parse_lookup ~head:false ~hyps:true penv) qs in
+      let lookup = List.rev_append qs lookup in
+      cc ~select ~lookup ~params ~children ~default ps
+    | PLapp("\\pattern",[],qs) ->
+      let qs = List.map
+          (parse_lookup ~head:false ~goal:true ~hyps:true penv) qs in
+      let lookup = List.rev_append qs lookup in
+      cc ~select ~lookup ~params ~children ~default ps
+    | PLapp("\\select",[],vs) ->
+      let vs = List.map (Pattern.pa_value penv) vs in
+      let select = List.rev_append vs select in
+      cc ~select ~lookup ~params ~children ~default ps
+    | PLapp("\\param",[],[param;value]) ->
+      let param = parse_name ctxt ~kind:"Parameter" param in
+      let value = Pattern.pa_value penv value in
+      let params = (param,value)::params in
+      cc ~select ~lookup ~params ~children ~default ps
+    | PLapp("\\child",[],[prefix;strategy]) ->
+      let subgoal = parse_name ctxt ~kind:"Subgoal" prefix in
+      let strategy = parse_name ctxt ~kind:"Strategy" strategy in
+      let children = (subgoal,strategy)::children in
+      cc ~select ~lookup ~params ~children ~default ps
+    | PLapp("\\children",[],[strategy]) ->
+      if default <> None then ctxt.error loc "Duplicate \\children parameter" ;
+      let default = Some (parse_name ctxt ~kind:"Strategy" strategy) in
+      cc ~select ~lookup ~params ~children ~default ps
+    | _ -> ctxt.error loc "Tactic parameter expected (%a)" debug p
+
+let parse_alternatives ctxt p =
+  let loc = p.lexpr_loc in
+  match p.lexpr_node with
+  | PLvar("\\default") -> [ Default ]
+  | PLapp("\\prover",[],ps) ->
+    let prvs,timeout = parse_provers ctxt [] None ps in
+    [ Provers(prvs,timeout) ]
+  | PLapp("\\tactic",[],p::ps) ->
+    let tactic = parse_name ctxt ~kind:"tactic" p in
+    [ parse_tactic_params ctxt (Pattern.context ctxt) ~tactic
+        ~select:[] ~lookup:[] ~params:[] ~children:[] ~default:None ps ]
+  | PLapp("\\auto",[],ps) ->
+    List.map (fun p -> Auto (parse_name ctxt ~kind:"auto" p)) ps
+  | PLvar value | PLapp(value,[],[]) -> [ Strategy { loc ; value } ]
+  | _ -> ctxt.error loc "Strategy definition expected (%a)" debug p
+
+(* -------------------------------------------------------------------------- *)
+(* --- Strategy Parser                                                    --- *)
+(* -------------------------------------------------------------------------- *)
+
+let parse_strategy_name ctxt loc = function
+  | [] -> ctxt.error loc "Empty strategy"
+  | p::ps ->
+    match p.lexpr_node with
+    | PLnamed(value,p) -> { loc ; value }, p::ps
+    | _ -> ctxt.error loc "Missing strategy name (%a)" debug p
+
+let parse_strategy ctxt loc ps =
+  let name,ps = parse_strategy_name ctxt loc ps in
+  try
+    let old = Hashtbl.find strategies name.value in
+    ctxt.error loc "Duplicate strategy definition ('%s', at %a)"
+      name.value Location.pretty old.name.loc
+  with Not_found ->
+    let alternatives = List.concat @@ List.map (parse_alternatives ctxt) ps in
+    let strategy = { name ; alternatives } in
+    let id = incr kid ; !kid in
+    Hashtbl.add strategies name.value strategy ;
+    Hashtbl.add sid id strategy ; Ext_id id
+
+(* -------------------------------------------------------------------------- *)
+(* --- Proof Parser                                                       --- *)
+(* -------------------------------------------------------------------------- *)
+
+let parse_hints ctxt p =
+  let loc = p.lexpr_loc in
+  match p.lexpr_node with
+  | PLvar x -> [x]
+  | PLconstant(StringConstant x) -> String.split_on_char ',' x
+  | _ -> ctxt.error loc "Proof hint expected (see -wp-prop) (%a)" debug p
+
+let parse_proofs ctxt loc ps =
+  let name , ps = parse_strategy_name ctxt loc ps in
+  let strategy = name.value in
+  if not (Hashtbl.mem strategies strategy) then
+    ctxt.error name.loc "Unknown strategy '%s'" strategy ;
+  let props = List.concat @@ List.map (parse_hints ctxt) ps in
+  let hint = (strategy, props) in
+  revhints := hint :: !revhints ;
+  let id = incr kid ; !kid in
+  Hashtbl.add hid id hint ; Ext_id id
+
+(* -------------------------------------------------------------------------- *)
+(* --- Strategy ACSL Extensions                                           --- *)
+(* -------------------------------------------------------------------------- *)
+
+let registered = ref false
+let register () =
+  if not !registered && Wp_parameters.StrategyEngine.get () then
+    begin
+      registered := true ;
+      let printer hmap pp _ fmt = function
+        | Ext_id id -> Option.iter (pp fmt) (Hashtbl.find_opt hmap id)
+        | _ -> () in
+      Acsl_extension.register_global "strategy"
+        ~printer:(printer sid pp_strategy) parse_strategy false ;
+      Acsl_extension.register_global "proof"
+        ~printer:(printer hid pp_hint) parse_proofs false ;
+    end
+
+let () = Cmdline.run_after_configuring_stage register
+
+(* -------------------------------------------------------------------------- *)
+(* --- Strategy Resolution                                                --- *)
+(* -------------------------------------------------------------------------- *)
+
+let name s = s.name.value
+let loc s = s.name.loc
+let find = Hashtbl.find_opt strategies
+let resolve name =
+  try Some (Hashtbl.find strategies name.value)
+  with Not_found ->
+    Wp_parameters.error ~source:(fst name.loc) ~once:true
+      "Strategy '%s' undefined (skipped)." name.value ;
+    None
+
+let resolve_auto name =
+  try Some (Strategy.lookup ~id:name.value)
+  with Not_found ->
+    Wp_parameters.error ~source:(fst name.loc) ~once:true
+      "Auto-Strategy '%s' not found (skipped)." name.value ;
+    None
+
+let resolve_prover name =
+  let result = VCS.parse_prover name.value in
+  if result = None then
+    Wp_parameters.error ~source:(fst name.loc) ~once:true
+      "Prover '%s' not found (skipped)." name.value ;
+  result
+
+let resolve_tactic name =
+  try Some (Tactical.lookup ~id:name.value)
+  with Not_found ->
+    Wp_parameters.error ~source:(fst name.loc) ~once:true
+      "Tactical '%s' not found (skipped alternative)." name.value ;
+    None
+
+(* -------------------------------------------------------------------------- *)
+(* --- Strategy Checking                                                  --- *)
+(* -------------------------------------------------------------------------- *)
+
+let check_prover p = ignore @@ resolve_prover p
+let check_strategy s = ignore @@ resolve s
+
+let check_parameter env (t : Tactical.tactical) (p,v) =
+  try
+    let prm = List.find (fun q -> Tactical.pident q = p.value) t#params in
+    match prm with
+    | Checkbox _ -> Pattern.typecheck_value env ~tau:Qed.Logic.Bool v
+    | _ -> ()
+  with Not_found ->
+    Wp_parameters.error ~source:(fst p.loc) ~once:true
+      "Parameter '%s' not found in tactic '%s'"
+      p.value t#id
+
+let check_alternative = function
+  | Default -> ()
+  | Strategy s -> ignore @@ resolve s
+  | Auto s -> ignore @@ resolve_auto s
+  | Provers(pvs,_) -> List.iter check_prover pvs
+  | Tactic { tactic ; lookup ; params ; children ; default } ->
+    begin
+      let env = Pattern.env () in
+      List.iter (Pattern.typecheck_lookup env) lookup ;
+      Option.iter
+        (fun tactical ->
+           List.iter (check_parameter env tactical) params ;
+        ) (resolve_tactic tactic) ;
+      List.iter (fun (_,s) -> check_strategy s) children ;
+      Option.iter check_strategy default ;
+    end
+
+let typecheck () =
+  Hashtbl.iter
+    (fun _ s -> List.iter check_alternative s.alternatives) strategies
+
+(* -------------------------------------------------------------------------- *)
+(* --- Strategy Hints                                                     --- *)
+(* -------------------------------------------------------------------------- *)
+
+let iter f =
+  let module M = Map.Make(String) in
+  let pool = ref M.empty in
+  Hashtbl.iter (fun a s -> pool := M.add a s !pool) strategies ;
+  M.iter (fun _ s -> f s) !pool
+
+let default () =
+  List.filter_map
+    (fun s ->
+       try Some (Hashtbl.find strategies s)
+       with Not_found ->
+         Wp_parameters.warning ~current:false ~once:true
+           "Invalid -wp-strategy '%s' (undefined strategy name)" s ;
+         None
+    ) @@
+  Wp_parameters.DefaultStrategies.get ()
+
+let hints ?node goal =
+  let pool = ref [] in
+  let add s = if not @@ List.memq s !pool then pool := s :: !pool in
+  let addname name = Option.iter add @@ Hashtbl.find_opt strategies name in
+  Option.iter addname (Option.bind node ProofEngine.get_hint) ;
+  let pid = goal.Wpo.po_pid in
+  List.iter
+    (fun (name,ps) ->
+       if WpPropId.select_by_name ps pid then addname name
+    ) !revhints ;
+  List.iter add @@ List.rev @@ default () ;
+  List.rev !pool
+
+let has_hint goal =
+  let pid = goal.Wpo.po_pid in
+  List.exists (fun (_,ps) -> WpPropId.select_by_name ps pid) !revhints
+
+(* -------------------------------------------------------------------------- *)
+(* --- Strategy Forward Step                                              --- *)
+(* -------------------------------------------------------------------------- *)
+
+let alternatives s = s.alternatives
+
+let timeout = function
+  | Some tm -> tm | None -> float @@ Wp_parameters.Timeout.get ()
+
+let provers ?(default=[]) = function
+  | Provers([],tm) -> default, timeout tm
+  | Provers(ps,tm) -> List.filter_map resolve_prover ps, timeout tm
+  | Default | Strategy _ | Tactic _ | Auto _ -> [],0.0
+
+let fallback = function
+  | Strategy s -> resolve s
+  | Tactic _ | Auto _ | Provers _ -> None
+  | Default -> Some {
+      name = { value = "\\default" ; loc = Position.(unknown,unknown) } ;
+      alternatives = List.map (fun s -> Strategy s.name) @@ default () ;
+    }
+
+let auto = function
+  | Default | Strategy _  | Tactic _ | Provers _ -> None
+  | Auto s -> resolve_auto s
+
+(* -------------------------------------------------------------------------- *)
+(* --- Strategy Tactical Step                                             --- *)
+(* -------------------------------------------------------------------------- *)
+
+let tactical a =
+  match resolve_tactic a with None -> raise Not_found | Some t -> t
+
+let parameter (t : Tactical.tactical) a =
+  try List.find (fun p -> Tactical.pident p = a.value) t#params
+  with Not_found ->
+    Wp_parameters.error ~source:(fst a.loc) ~once:true
+      "Parameter '%s' not found (skipped alternative)." a.value ;
+    raise Not_found
+
+let rec bind sigma sequent = function
+  | [] -> sigma
+  | lookup::binders ->
+    match Pattern.psequent lookup sigma sequent with
+    | None -> raise Not_found
+    | Some sigma -> bind sigma sequent binders
+
+let select sigma ?goal = function
+  | [] ->
+    begin
+      match goal with
+      | None -> Tactical.Empty
+      | Some p -> Tactical.(Clause (Goal p))
+    end
+  | [v] -> Pattern.select sigma v
+  | vs -> Tactical.Multi (List.map (Pattern.select sigma) vs)
+
+let configure tactic sigma (a,v) =
+  match parameter tactic a with
+  | Checkbox fd ->
+    begin
+      try tactic#set_field fd (Pattern.bool v)
+      with Not_found ->
+        Wp_parameters.error ~source:(fst a.loc)
+          "Expected boolean for parameter '%s' (%a)" a.value
+          Pattern.pp_value v ;
+        raise Not_found
+    end
+  | Spinner(fd,_) ->
+    begin
+      let value = Pattern.select sigma v in
+      match Tactical.get_int value with
+      | Some v -> tactic#set_field fd v
+      | None ->
+        Wp_parameters.error ~source:(fst a.loc)
+          "Expected integer for parameter '%s'@ (%a)" a.value
+          Tactical.pp_selection value ;
+        raise Not_found
+    end
+  | Composer(fd,_) -> tactic#set_field fd (Pattern.select sigma v)
+  | Selector(fd,vs,_) ->
+    begin
+      try
+        let id = Pattern.string v in
+        let v = List.find (fun v -> v.Tactical.vid = id) vs in
+        tactic#set_field fd v.value
+      with Not_found ->
+        Wp_parameters.error ~source:(fst a.loc)
+          "Expected string for parameter '%s'@ (%a)" a.value
+          Pattern.pp_value v ;
+        raise Not_found
+    end
+  | Search(fd,_,lookup) ->
+    begin
+      try
+        let id = Pattern.string v in
+        let v = lookup id in
+        tactic#set_field fd (Some v)
+      with Not_found ->
+        Wp_parameters.error ~source:(fst a.loc)
+          "Expected string for parameter '%s'@ (%a)" a.value
+          Pattern.pp_value v ;
+        raise Not_found
+    end
+
+let subgoal (children : (string loc * string loc) list)
+    (default : string loc option) (goal,node) =
+  let hint = List.find_map (fun (g,s) ->
+      if Extlib.string_prefix g.value goal then Some s else None
+    ) children in
+  begin
+    match hint, default with
+    | None, None -> ()
+    | Some s , _ | None , Some s ->
+      if not @@ Hashtbl.mem strategies s.value then
+        Wp_parameters.error ~source:(fst s.loc)
+          "Unknown strategy '%s' (skipped)" s.value
+      else ProofEngine.set_hint node s.value
+  end ; node
+
+let tactic tree node strategy = function
+  | Default | Strategy _ | Auto _ | Provers _ -> None
+  | Tactic t ->
+    try
+      let tactic = tactical t.tactic in
+      let pool = ProofEngine.pool tree in
+      let title = tactic#title in
+      let ctxt = ProofEngine.node_context node in
+      let sequent = snd @@ Wpo.compute @@ ProofEngine.goal node in
+      let console = new ProofScript.console ~pool ~title in
+      let subgoals = WpContext.on_context ctxt
+          begin fun () ->
+            let sigma = bind Pattern.empty sequent t.lookup in
+            let goal = if t.lookup = [] then Some (snd sequent) else None in
+            let selection = select sigma ?goal t.select in
+            List.iter (configure tactic sigma) t.params ;
+            match Lang.local ~pool (tactic#select console) selection with
+            | exception (Not_found | Exit) -> raise Not_found
+            | Not_applicable ->
+              raise Not_found
+            | exception exn when Wp_parameters.protect exn ->
+              Wp_parameters.warning ~source:(fst t.tactic.loc)
+                "Tactical '%s' configuration error (%s)"
+                t.tactic.value (Printexc.to_string exn) ;
+              raise Not_found
+            | Not_configured ->
+              Wp_parameters.error ~source:(fst t.tactic.loc)
+                "Tactical '%s' configuration error"
+                t.tactic.value ;
+              raise Not_found
+            | Applicable process ->
+              let strategy = strategy.name.value in
+              let script = ProofScript.jtactic ~strategy tactic selection in
+              let fork = ProofEngine.fork tree ~anchor:node script process in
+              snd @@ ProofEngine.commit fork
+          end () in
+      Some (List.map (subgoal t.children t.default) subgoals)
+    with Not_found -> None
+
+(* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/gui/dgraph_helper.mli b/src/plugins/wp/ProofStrategy.mli
similarity index 56%
rename from src/plugins/gui/dgraph_helper.mli
rename to src/plugins/wp/ProofStrategy.mli
index e75b9f204147b5906fc306204300568dafbe4f96..90c5995b1f8ba0022ada4f5756ea4c67069b732f 100644
--- a/src/plugins/gui/dgraph_helper.mli
+++ b/src/plugins/wp/ProofStrategy.mli
@@ -1,9 +1,9 @@
 (**************************************************************************)
 (*                                                                        *)
-(*  This file is part of Frama-C.                                         *)
+(*  This file is part of WP plug-in of Frama-C.                           *)
 (*                                                                        *)
 (*  Copyright (C) 2007-2023                                               *)
-(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*    CEA (Commissariat a l'energie atomique et aux energies              *)
 (*         alternatives)                                                  *)
 (*                                                                        *)
 (*  you can redistribute it and/or modify it under the terms of the GNU   *)
@@ -20,23 +20,29 @@
 (*                                                                        *)
 (**************************************************************************)
 
-(** Creation of windows for displaying graphs. Only available
-    for lablgtk2. In lablgtk3 mode, the window will only display a
-    text saying that the feature is not available.
-*)
+open ProofEngine
 
-(** Create a new window displaying a graph.
-    @see <https://frama-c.com/download/frama-c-plugin-development-guide.pdf> Plug-in Development Guide *)
-val graph_window:
-  parent: GWindow.window ->
-  title:string ->
-  (packing:(GObj.widget -> unit) -> unit ->
-   <adapt_zoom: unit -> unit; ..>) ->
-  unit
+(* -------------------------------------------------------------------------- *)
+(* --- Proof Strategy Engine                                              --- *)
+(* -------------------------------------------------------------------------- *)
 
-(** Create a new window displaying a graph, by printing dot commands. *)
-val graph_window_through_dot:
-  parent: GWindow.window ->
-  title:string ->
-  (Format.formatter -> unit) ->
-  unit
+type strategy
+type alternative
+
+val typecheck : unit -> unit
+
+val name : strategy -> string
+val loc : strategy -> Cil_types.location
+val find : string -> strategy option
+val hints : ?node:ProofEngine.node -> Wpo.t -> strategy list
+val has_hint : Wpo.t -> bool
+
+val iter : (strategy -> unit) -> unit
+val default : unit -> strategy list
+val alternatives : strategy -> alternative list
+val provers : ?default:VCS.prover list -> alternative -> VCS.prover list * float
+val auto : alternative -> Strategy.heuristic option
+val fallback : alternative -> strategy option
+val tactic : tree -> node -> strategy -> alternative -> node list option
+
+(* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/wp/ProverScript.ml b/src/plugins/wp/ProverScript.ml
index 91eeaf02adc04b93508a1185c15b2c42fc73a8f5..feb73306307eecf2e682563f7ed1735cbeefe5c5 100644
--- a/src/plugins/wp/ProverScript.ml
+++ b/src/plugins/wp/ProverScript.ml
@@ -23,8 +23,7 @@
 open Tactical
 open ProofScript
 
-let dkey_pp_allgoals =
-  Wp_parameters.register_category "script:allgoals"
+let dkey_pp_allgoals = Wp_parameters.register_category "script:allgoals"
 
 (* -------------------------------------------------------------------------- *)
 (* --- Alternatives Ordering                                              --- *)
@@ -73,8 +72,8 @@ let jconfigure (console : #Tactical.feedback) jtactic goal =
     begin
       match verdict with
       | Applicable process when not console#has_error ->
-        let title = tactical#title in
-        let script = ProofScript.jtactic ~title tactical selection in
+        let strategy = jtactic.strategy in
+        let script = ProofScript.jtactic ?strategy tactical selection in
         Some (script , process)
       | _ -> None
     end
@@ -85,6 +84,7 @@ let jfork tree ?node jtactic =
     ~title:jtactic.header in
   try
     let anchor = ProofEngine.anchor tree ?node () in
+    Option.iter (ProofEngine.set_hint anchor) jtactic.strategy ;
     let goal = ProofEngine.goal anchor in
     let ctxt = ProofEngine.node_context anchor in
     match WpContext.on_context ctxt (jconfigure console jtactic) goal with
@@ -117,7 +117,8 @@ struct
     success : Wpo.t -> VCS.prover option -> unit ;
     depth : int ;
     width : int ;
-    auto : Strategy.heuristic list ;
+    auto : Strategy.heuristic list ; (* DEPRECATED *)
+    strategies : bool ;
     mutable signaled : bool ;
     backtrack : int ;
     mutable backtracking : backtracking option ;
@@ -219,11 +220,11 @@ struct
   let provers env = env.provers
 
   let make tree
-      ~valid ~failed ~provers
+      ~valid ~failed ~provers ~strategies
       ~depth ~width ~backtrack ~auto
       ~progress ~result ~success =
     { tree ; valid ; failed ; provers ;
-      depth ; width ; backtrack ; auto ;
+      depth ; width ; backtrack ; auto ; strategies ;
       progress ; result ; success ;
       backtracking = None ;
       signaled = false }
@@ -277,7 +278,7 @@ let prove_node env node prv =
   else Task.return false
 
 (* -------------------------------------------------------------------------- *)
-(* --- Auto & Seach Mode                                                  --- *)
+(* --- Auto & Seach Mode (DEPRECATED)                                     --- *)
 (* -------------------------------------------------------------------------- *)
 
 let rec auto env ?(depth=0) node : bool Task.task =
@@ -314,6 +315,98 @@ and autofork env ~depth fork =
   else
     ( Env.validate env ; Task.return true )
 
+(* -------------------------------------------------------------------------- *)
+(* --- Proof Strategy Alternatives                                        --- *)
+(* -------------------------------------------------------------------------- *)
+
+type solver = ProofEngine.node -> bool Task.task
+
+let success = Task.return true
+let failed = Task.return false
+let unknown : solver = fun _ -> failed
+
+let (+>>) (a : solver) (b : solver) : solver =
+  fun node -> a node >>= fun ok -> if ok then success else b node
+
+let rec sequence (f : 'a -> solver) = function
+  | [] -> unknown
+  | x::xs -> f x +>> sequence f xs
+
+let rec explore_strategy env process strategy : solver =
+  sequence
+    (explore_alternative env process strategy)
+    (ProofStrategy.alternatives strategy)
+
+and explore_alternative env process strategy alternative : solver =
+  explore_provers env alternative +>>
+  explore_tactic env process strategy alternative +>>
+  explore_auto env process alternative +>>
+  explore_fallback env process alternative
+
+and explore_provers env alternative : solver =
+  let provers,timeout =
+    ProofStrategy.provers ~default:env.Env.provers alternative in
+  sequence (explore_prover env timeout) provers
+
+and explore_prover env timeout prover node =
+  let wpo = ProofEngine.goal node in
+  let result = Cache.promote ~timeout @@ Wpo.get_result wpo prover in
+  if VCS.is_valid result then success else
+  if VCS.is_verdict result then failed else
+    let config = { VCS.default with timeout = Some timeout } in
+    Env.prove env wpo ~config prover
+
+and explore_tactic env process strategy alternative node =
+  match ProofStrategy.tactic env.tree node strategy alternative with
+  | None -> failed
+  | Some nodes -> List.iter process nodes ; success
+
+and explore_auto env process alternative node =
+  match ProofStrategy.auto alternative with
+  | None -> failed
+  | Some h ->
+    match ProverSearch.search env.tree ~anchor:node [h] with
+    | None -> failed
+    | Some fork ->
+      List.iter (fun (_,node) -> process node) @@
+      snd @@ ProofEngine.commit fork ; success
+
+and explore_fallback env process alternative node =
+  match ProofStrategy.fallback alternative with
+  | None -> failed
+  | Some strategy -> explore_strategy env process strategy node
+
+let explore_local_hint env process node =
+  if ProofEngine.depth node > env.Env.depth then failed
+  else
+    match ProofEngine.get_hint node with
+    | None -> failed
+    | Some s ->
+      match ProofStrategy.find s with
+      | None -> failed
+      | Some s -> explore_strategy env process s node
+
+let explore_further env process strategy node =
+  let marked =
+    match ProofEngine.get_hint node with
+    | None -> false
+    | Some s -> ProofStrategy.name strategy = s
+  in if marked then failed else explore_strategy env process strategy node
+
+let explore_further_hints env process =
+  let wpo = ProofEngine.main env.Env.tree in
+  sequence (explore_further env process) (ProofStrategy.hints wpo)
+
+let explore_hints env process =
+  explore_local_hint env process +>> explore_further_hints env process
+
+(* -------------------------------------------------------------------------- *)
+(* --- Automated Solving                                                  --- *)
+(* -------------------------------------------------------------------------- *)
+
+let automated env process : solver =
+  auto env +>> if env.Env.strategies then explore_hints env process else unknown
+
 (* -------------------------------------------------------------------------- *)
 (* --- Apply Script Tactic                                                --- *)
 (* -------------------------------------------------------------------------- *)
@@ -337,17 +430,17 @@ let rec crawl env on_child node = function
 
   | [] ->
     let node = ProofEngine.anchor (Env.tree env) ?node () in
-    auto env node >>= fun ok ->
+    automated env on_child node >>= fun ok ->
     if ok then Env.validate env else Env.stuck env ;
     Task.return ()
 
-  | Error(msg,json) :: alternative ->
+  | Error(msg,json) :: alternatives ->
     Wp_parameters.warning "@[<hov 2>Script Error: on goal %a@\n%S: %a@]@."
       WpPropId.pretty (Env.goal env node).po_pid
       msg Json.pp json ;
-    crawl env on_child node alternative
+    crawl env on_child node alternatives
 
-  | Prover( prv , res ) :: alternative ->
+  | Prover( prv , res ) :: alternatives ->
     begin
       let task =
         if Env.play env prv res then
@@ -358,12 +451,12 @@ let rec crawl env on_child node = function
       let continue ok =
         if ok
         then (Env.validate env ; Task.return ())
-        else crawl env on_child node alternative
+        else crawl env on_child node alternatives
       in
       task >>= continue
     end
 
-  | Tactic( _ , jtactic , subscripts ) :: alternative ->
+  | Tactic( _ , jtactic , subscripts ) :: alternatives ->
     begin
       try
         let residual = apply env node jtactic subscripts in
@@ -384,7 +477,7 @@ let rec crawl env on_child node = function
           (Printexc.to_string exn)
           Json.pp jtactic.params
           Json.pp jtactic.select ;
-        crawl env on_child node alternative
+        crawl env on_child node alternatives
     end
 
 (* -------------------------------------------------------------------------- *)
@@ -412,7 +505,7 @@ let rec process env node =
 
 let task
     ~valid ~failed ~provers
-    ~depth ~width ~backtrack ~auto
+    ~depth ~width ~backtrack ~auto ~scratch ~strategies
     ~start ~progress ~result ~success wpo =
   begin fun () ->
     Wp_parameters.debug ~dkey:dkey_pp_allgoals "%a" Wpo.pp_goal_flow wpo ;
@@ -421,12 +514,14 @@ let task
     then
       ( success wpo (Some VCS.Qed) ; Task.return ())
     else
-      let json = ProofSession.load wpo in
-      let script = Priority.sort (ProofScript.decode json) in
+      let script =
+        if scratch then [] else
+          Priority.sort @@ ProofScript.decode @@ ProofSession.load wpo
+      in
       let tree = ProofEngine.proof ~main:wpo in
       let env = Env.make tree
           ~valid ~failed ~provers
-          ~depth ~width ~backtrack ~auto
+          ~depth ~width ~backtrack ~auto ~strategies
           ~progress ~result ~success in
       crawl env (process env) None script >>?
       (fun _ -> ProofEngine.forward tree) ;
@@ -437,9 +532,10 @@ let task
 (* -------------------------------------------------------------------------- *)
 
 type 'a process =
-  ?valid:bool -> ?failed:bool -> ?provers:VCS.prover list ->
+  ?valid:bool -> ?failed:bool -> ?scratch:bool -> ?provers:VCS.prover list ->
   ?depth:int -> ?width:int -> ?backtrack:int ->
   ?auto:Strategy.heuristic list ->
+  ?strategies:bool ->
   ?start:(Wpo.t -> unit) ->
   ?progress:(Wpo.t -> string -> unit) ->
   ?result:(Wpo.t -> VCS.prover -> VCS.result -> unit) ->
@@ -451,23 +547,25 @@ let skip2 _ _ = ()
 let skip3 _ _ _ = ()
 
 let prove
-    ?(valid = true) ?(failed = true) ?(provers = [])
+    ?(valid = true) ?(failed = true) ?(scratch = false) ?(provers = [])
     ?(depth = 0) ?(width = 0) ?(backtrack = 0) ?(auto = [])
+    ?(strategies = false)
     ?(start = skip1) ?(progress = skip2) ?(result = skip3) ?(success = skip2)
     wpo =
   Task.todo (task
                ~valid ~failed ~provers
-               ~depth ~width ~backtrack ~auto
+               ~depth ~width ~backtrack ~auto ~scratch ~strategies
                ~start ~progress ~result ~success wpo)
 
 let spawn
-    ?(valid = true) ?(failed = true) ?(provers = [])
+    ?(valid = true) ?(failed = true) ?(scratch = false) ?(provers = [])
     ?(depth = 0) ?(width = 0) ?(backtrack = 0) ?(auto = [])
+    ?(strategies = false)
     ?(start = skip1) ?(progress = skip2) ?(result = skip3) ?(success = skip2)
     wpo =
   schedule (task
               ~valid ~failed ~provers
-              ~depth ~width ~backtrack ~auto
+              ~depth ~width ~backtrack ~auto ~scratch ~strategies
               ~start ~progress ~result ~success wpo)
 
 let search
@@ -477,7 +575,7 @@ let search
   begin
     let env = Env.make tree
         ~valid:false ~failed:false ~provers
-        ~depth ~width ~backtrack ~auto
+        ~depth ~width ~backtrack ~auto ~strategies:false
         ~progress ~result ~success in
     schedule
       begin fun () ->
@@ -488,6 +586,28 @@ let search
       end
   end
 
+let explore ?(depth=0) ?(strategy)
+    ?(progress = skip2) ?(result=skip3) ?(success = skip2)
+    tree node =
+  begin
+    let depth = ProofEngine.depth node + depth in
+    let env : Env.t =
+      Env.make tree ~valid:false ~failed:false
+        ~strategies:(strategy <> None)
+        ~provers:[] ~depth ~width:0 ~backtrack:0 ~auto:[]
+        ~progress ~result ~success in
+    schedule
+      begin fun () ->
+        let solver =
+          match strategy with
+          | None -> explore_hints env (process env)
+          | Some s -> explore_strategy env (fun _ -> ()) s
+        in solver node >>= fun ok ->
+        if ok then Env.validate ~finalize:true env else Env.stuck env ;
+        Task.return ()
+      end
+  end
+
 (* -------------------------------------------------------------------------- *)
 (* --- Save Session                                                       --- *)
 (* -------------------------------------------------------------------------- *)
@@ -507,11 +627,6 @@ let has_proof wpo =
       (Hashtbl.add proofs wid ok ; ok)
     else false
 
-let save ~stdout wpo =
-  let script = ProofEngine.script (ProofEngine.proof ~main:wpo) in
-  Hashtbl.remove proofs wpo.Wpo.po_gid ;
-  ProofSession.save ~stdout wpo (ProofScript.encode script)
-
 let get wpo =
   match ProofEngine.get wpo with
   | `None -> `None
diff --git a/src/plugins/wp/ProverScript.mli b/src/plugins/wp/ProverScript.mli
index 90452f6f98a593fe6429aad6d40265075b069af3..022ffd6b573f9210ce481d0657eff67d0182e9fb 100644
--- a/src/plugins/wp/ProverScript.mli
+++ b/src/plugins/wp/ProverScript.mli
@@ -24,6 +24,7 @@ open VCS
 
 (** - [valid]: Play provers with valid result (default: true)
     - [failed]: Play provers with invalid result (default: true)
+    - [scratch]: Discard existing script (default: false)
     - [provers]: Additional list of provers to {i try} when stuck
     - [depth]: Strategy search depth (default: 0)
     - [width]: Strategy search width (default: 0)
@@ -33,11 +34,13 @@ open VCS
 type 'a process =
   ?valid:bool ->
   ?failed:bool ->
+  ?scratch:bool ->
   ?provers:prover list ->
   ?depth:int ->
   ?width:int ->
   ?backtrack:int ->
   ?auto:Strategy.heuristic list ->
+  ?strategies:bool ->
   ?start:(Wpo.t -> unit) ->
   ?progress:(Wpo.t -> string -> unit) ->
   ?result:(Wpo.t -> prover -> result -> unit) ->
@@ -60,5 +63,14 @@ val search :
   ProofEngine.node ->
   unit
 
+val explore :
+  ?depth:int ->
+  ?strategy:ProofStrategy.strategy ->
+  ?progress:(Wpo.t -> string -> unit) ->
+  ?result:(Wpo.t -> prover -> result -> unit) ->
+  ?success:(Wpo.t -> prover option -> unit) ->
+  ProofEngine.tree ->
+  ProofEngine.node ->
+  unit
+
 val get : Wpo.t -> [ `Script | `Proof | `Saved | `None ]
-val save : stdout:bool -> Wpo.t -> unit
diff --git a/src/plugins/wp/ProverSearch.ml b/src/plugins/wp/ProverSearch.ml
index 697016c96e9f6857d9d80bffb11ef6987289c8b5..f2872d66e8c98261d90699a1a7f498b8f6bc7fcf 100644
--- a/src/plugins/wp/ProverSearch.ml
+++ b/src/plugins/wp/ProverSearch.ml
@@ -34,8 +34,7 @@ let configure (console : #Tactical.feedback) strategy =
   in
   match Lang.local ~pool:console#pool verdict () with
   | Applicable process when not console#has_error ->
-    let title = tactical#title in
-    let script = ProofScript.jtactic ~title tactical selection in
+    let script = ProofScript.jtactic tactical selection in
     Some (script , process)
   | _ -> None
 
diff --git a/src/plugins/wp/ProverTask.ml b/src/plugins/wp/ProverTask.ml
index 4746c8b00f0551b1b858876e32079de5c4e53f4f..76808660184319c903f6b9d4c49e64fdbaf88ad7 100644
--- a/src/plugins/wp/ProverTask.ml
+++ b/src/plugins/wp/ProverTask.ml
@@ -182,7 +182,7 @@ class command name =
     val mutable once = true
     val mutable cmd = name
     val mutable param : string list = []
-    val mutable timeout = 0
+    val mutable timeout = 0.0
     val mutable validout = []
     val mutable validerr = []
     val mutable timers = []
diff --git a/src/plugins/wp/ProverTask.mli b/src/plugins/wp/ProverTask.mli
index db6356dbe219ca14fbbf6551cd2fce6f81bb9ff1..a37c089fdbefc34b97ab1064128a91edfa59473d 100644
--- a/src/plugins/wp/ProverTask.mli
+++ b/src/plugins/wp/ProverTask.mli
@@ -77,7 +77,7 @@ class virtual command : string ->
     method add_float : name:string -> value:float -> unit
     method add_parameter : name:string -> (unit -> bool) -> unit
     method add_list : name:string -> string list -> unit
-    method timeout : int -> unit
+    method timeout : float -> unit
     method validate_time : (float -> unit) -> unit
     method validate_pattern : ?logs:logs -> ?repeat:bool ->
       Str.regexp -> (pattern -> unit) -> unit
diff --git a/src/plugins/wp/ProverWhy3.ml b/src/plugins/wp/ProverWhy3.ml
index 834e02cd47ed7a8e2c306e6782c4261e66fe1199..7a9bd2fa1a7006a27e8e8c29afa5de3a778f420a 100644
--- a/src/plugins/wp/ProverWhy3.ml
+++ b/src/plugins/wp/ProverWhy3.ml
@@ -144,9 +144,8 @@ let lfun_name (lfun:Lang.lfun) =
   match lfun with
   | ACSL f -> Qed.Engine.F_call (Lang.logic_id f)
   | CTOR c -> Qed.Engine.F_call (Lang.ctor_id c)
-  | Model({m_source=Generated(_,n)}) -> Qed.Engine.F_call n
-  | Model({m_source=Extern e}) -> e.Lang.ext_link
-
+  | FUN({m_source=Generated(_,n)}) -> Qed.Engine.F_call n
+  | FUN({m_source=Extern e}) -> e.Lang.ext_link
 
 let coerce ~cnv sort expected r =
   match sort, expected with
@@ -1152,7 +1151,7 @@ type prover_call = {
   prover : Why3Provers.t ;
   call : Why3.Call_provers.prover_call ;
   steps : int option ;
-  timeout : int ;
+  timeout : float ;
   mutable timeover : float option ;
   mutable interrupted : bool ;
   mutable killed : bool ;
@@ -1163,11 +1162,11 @@ let ping_prover_call ~config p =
   | NoUpdates
   | ProverStarted ->
     let () =
-      if p.timeout > 0 then
+      if p.timeout > 0.0 then
         match p.timeover with
         | None ->
           let started = Unix.time () in
-          p.timeover <- Some (started +. 2.0 +. float p.timeout)
+          p.timeover <- Some (started +. 2.0 +. p.timeout)
         | Some timeout ->
           let time = Unix.time () in
           if time > timeout then
@@ -1187,7 +1186,7 @@ let ping_prover_call ~config p =
   | ProverFinished pr ->
     let r =
       match pr.pr_answer with
-      | Timeout -> VCS.timeout (int_of_float pr.pr_time)
+      | Timeout -> VCS.timeout pr.pr_time
       | Valid -> VCS.result ~time:pr.pr_time ~steps:pr.pr_steps VCS.Valid
       | Invalid -> VCS.result ~time:pr.pr_time ~steps:pr.pr_steps VCS.Invalid
       | OutOfMemory -> VCS.failed "out of memory"
@@ -1211,11 +1210,11 @@ let ping_prover_call ~config p =
     Task.Return (Task.Result r)
 
 let call_prover_task ~timeout ~steps ~config prover call =
-  Wp_parameters.debug ~dkey "Why3 run prover %a with timeout %d, steps %d@."
+  Wp_parameters.debug ~dkey "Why3 run prover %a with timeout %f, steps %d@."
     Why3.Whyconf.print_prover prover
-    (Why3.Opt.get_def (-1) timeout)
-    (Why3.Opt.get_def (-1) steps) ;
-  let timeout = match timeout with None -> 0 | Some tlimit -> tlimit in
+    (Why3.Opt.get_def (0.0) timeout)
+    (Why3.Opt.get_def 0 steps) ;
+  let timeout = match timeout with None -> 0.0 | Some tlimit -> tlimit in
   let pcall = {
     call ; prover ;
     killed = false ;
@@ -1256,7 +1255,6 @@ let run_batch pconf driver ~config ?script ~timeout ~steplimit prover task =
   let steps = match steplimit with Some 0 -> None | _ -> steplimit in
   let limit =
     let config = Why3.Whyconf.get_main @@ Why3Provers.config () in
-    let timeout = Option.map float_of_int timeout in
     let memlimit = Why3.Whyconf.memlimit config in
     let def = Why3.Call_provers.empty_limit in
     { Why3.Call_provers.limit_time = Why3.Opt.get_def def.limit_time timeout;
@@ -1266,7 +1264,11 @@ let run_batch pconf driver ~config ?script ~timeout ~steplimit prover task =
   let with_steps = match steps, pconf.Why3.Whyconf.command_steps with
     | None, _ -> false
     | Some _, Some _ -> true
-    | Some _, None -> false
+    | Some _, None ->
+      Wp_parameters.warning ~once:true ~current:false
+        "%a does not support steps limit (ignored option)"
+        Why3.Whyconf.print_prover prover ;
+      false
   in
   let steps = if with_steps then steps else None in
   let command = Why3.Whyconf.get_complete_command pconf ~with_steps in
@@ -1343,7 +1345,7 @@ let prepare ~mode wpo driver task =
 
 let interactive ~mode wpo pconf ~config driver prover task =
   let time = Wp_parameters.InteractiveTimeout.get () in
-  let timeout = if time <= 0 then None else Some time in
+  let timeout = if time <= 0 then None else Some (float time) in
   match prepare ~mode wpo driver task with
   | None ->
     Wp_parameters.warning ~once:true ~current:false
diff --git a/src/plugins/wp/ProverWhy3.mli b/src/plugins/wp/ProverWhy3.mli
index 8f00f859dfa4a8b5200980a0ff053b2476e24efb..24aac04061dc75bf6f294910899857c8f49e2e4f 100644
--- a/src/plugins/wp/ProverWhy3.mli
+++ b/src/plugins/wp/ProverWhy3.mli
@@ -26,7 +26,7 @@ val add_specific_equality:
   unit
 (** Equality used in the goal, simpler to prove than polymorphic equality *)
 
-val prove : ?mode:VCS.mode -> ?timeout:int -> ?steplimit:int ->
+val prove : ?mode:VCS.mode -> ?timeout:float -> ?steplimit:int ->
   prover:Why3Provers.t -> Wpo.t -> VCS.result Task.task
 (** Return NoResult if it is already proved by Qed *)
 
diff --git a/src/plugins/wp/RegionAnnot.ml b/src/plugins/wp/RegionAnnot.ml
index b0ca2f6e741103fa301c20f993fcca8e2a10576f..d32aaf7a785c4fabd03713b406ff132861ab5a5a 100644
--- a/src/plugins/wp/RegionAnnot.ml
+++ b/src/plugins/wp/RegionAnnot.ml
@@ -489,12 +489,18 @@ let specified =
       ignore (Str.search_forward re model 0) ; true
     with Not_found -> false
 
+let registered = ref false
 let register () =
-  if Wp.Region.get () || Wp.Region_annot.get () ||
-     List.exists specified (Wp.Model.get ())
+  if not !registered && (
+      Wp.Region.get () || Wp.Region_annot.get () ||
+      List.exists specified (Wp.Model.get ())
+    )
   then
-    Acsl_extension.register_behavior
-      "region" typecheck ~printer:pp_extension false
+    begin
+      registered := true ;
+      Acsl_extension.register_behavior "region"
+        typecheck ~printer:pp_extension false
+    end
 
 let () = Cmdline.run_after_configuring_stage register
 
diff --git a/src/plugins/wp/Splitter.ml b/src/plugins/wp/Splitter.ml
index 3f5fce9f93f2c8e3ace6ac0c84415a0d05a455b1..c2090c840991f5da2d4d15a84531bbe0b89cce27 100644
--- a/src/plugins/wp/Splitter.ml
+++ b/src/plugins/wp/Splitter.ml
@@ -157,12 +157,14 @@ and collect merge k vs = function
 
 let bytags (k,_) (k',_) = Tags.compare k k'
 
-let group tag merge m =
+let apply tag merge m =
+  (* compaction is only required when some split in m already has the tag *)
   let compaction = ref false in
   let m = List.sort bytags
       (List.map
          (fun (tgs,v) ->
-            if not !compaction && Tags.mem tag tgs then compaction := true ;
+            if not !compaction && Tags.mem tag tgs then
+              compaction := true ;
             Tags.add tag tgs , v) m)
   in if !compaction then compact merge m else m
 
diff --git a/src/plugins/wp/Splitter.mli b/src/plugins/wp/Splitter.mli
index 0e70bca587ec65ad7dac4d5b2731fc155adf5c12..4fc82dab9269d959dc20159b16cd7591e3fc4230 100644
--- a/src/plugins/wp/Splitter.mli
+++ b/src/plugins/wp/Splitter.mli
@@ -44,7 +44,7 @@ type 'a t
 
 val empty : 'a t
 val singleton : 'a -> 'a t
-val group : tag -> ('a list -> 'a) -> 'a t -> 'a t
+val apply : tag -> ('a list -> 'a) -> 'a t -> 'a t
 
 val union : ('a -> 'a -> 'a) -> 'a t -> 'a t -> 'a t
 val merge :
diff --git a/src/plugins/wp/Stats.ml b/src/plugins/wp/Stats.ml
index 60caa14eb5be10d93b07163d2f61dd2d31b3a182..50449ec8a3b466e59467fa38fc3610b3f368ae4f 100644
--- a/src/plugins/wp/Stats.ml
+++ b/src/plugins/wp/Stats.ml
@@ -86,9 +86,10 @@ let ptime t valid =
   { tmin = t ; tval = t ; tmax = t ; time = t ; tnbr = 1.0 ;
     success = if valid then 1.0 else 0.0 }
 
-let pqed r = ptime r.solver_time (VCS.is_valid r)
-let presult r = ptime r.prover_time (VCS.is_valid r)
+let pqed r = if VCS.is_valid r then ptime r.solver_time true else pzero
+let presult r = if VCS.is_valid r then ptime r.prover_time true else pzero
 let psolver r = ptime r.solver_time false
+let psmoked = { pzero with success = 1.0 }
 
 (* -------------------------------------------------------------------------- *)
 (* --- Global Stats                                                       --- *)
@@ -181,9 +182,7 @@ let results ~smoke prs =
       let cached = List.fold_left
           (fun c (_,r) -> if r.VCS.cached then succ c else c)
           0 passed in
-      let stucked = List.map
-          (fun (p,r) -> p, ptime r.prover_time true)
-          passed in
+      let stucked = List.map (fun (p,_) -> p,psmoked) passed in
       let solver = List.fold_left
           (fun t (_,r) -> t +. r.solver_time)
           0.0 passed in
diff --git a/src/plugins/wp/TacChoice.ml b/src/plugins/wp/TacChoice.ml
index ad538abb747f342cd3fc434edbb18064a9ef7713..27d558c7afbb2b0b75a12c6deec0a8b06c26c022 100644
--- a/src/plugins/wp/TacChoice.ml
+++ b/src/plugins/wp/TacChoice.ml
@@ -54,13 +54,21 @@ class absurd =
     inherit Tactical.make
         ~id:"Wp.absurd"
         ~title:"Absurd"
-        ~descr:"Contradict an Hypothesis"
+        ~descr:"Contradict the Goal or an Hypothesis"
         ~params:[]
 
     method select _feedback (s : Tactical.selection) =
       match s with
-      | Empty | Compose _ | Inside _ | Clause(Goal _) | Multi _
+      | Empty | Compose _ | Inside _ | Multi _
         -> Not_applicable
+      | Clause(Goal _) ->
+        let absurd (seq,goal) =
+          let goal = F.p_not goal in
+          let step = Conditions.step ~descr:"Absurd" (When goal) in
+          let hyps = Conditions.list seq in
+          let hyps = Conditions.sequence (hyps @ [step]) in
+          [ "Absurd", (hyps , F.p_false) ]
+        in Applicable absurd
       | Clause(Step s) ->
         begin
           match s.condition with
diff --git a/src/plugins/wp/TacCompute.ml b/src/plugins/wp/TacCompute.ml
new file mode 100644
index 0000000000000000000000000000000000000000..07cbeb1d70043b2755ce29dcf33438576fa958cf
--- /dev/null
+++ b/src/plugins/wp/TacCompute.ml
@@ -0,0 +1,80 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of WP plug-in of Frama-C.                           *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2023                                               *)
+(*    CEA (Commissariat a l'energie atomique et aux energies              *)
+(*         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 Lang
+open Tactical
+
+(* -------------------------------------------------------------------------- *)
+(* --- Compute Term                                                       --- *)
+(* -------------------------------------------------------------------------- *)
+
+exception Split of F.term * F.term * F.term
+exception Unfold of F.term * Lang.lfun * F.term
+
+let head e =
+  if F.lc_closed e && not @@ F.is_primitive e then
+    match F.repr e with
+    | If(c,a,b) -> raise (Split(c,a,b))
+    | Fun(f,es) -> raise (Unfold(e,f,TacUnfold.unfold f es))
+    | _ -> ()
+
+let process (fd : Tactical.feedback) ?at e =
+  try
+    let q = Queue.create () in
+    let m = ref F.Tset.empty in
+    let lookup e =
+      head e ;
+      m := F.Tset.add e !m ;
+      F.lc_iter (fun e -> Queue.push e q) e
+    in
+    lookup e ;
+    while not @@ Queue.is_empty q do
+      let e = Queue.pop q in
+      if not @@ F.Tset.mem e !m then lookup e ;
+    done ;
+    Not_applicable
+  with
+  | Split(a,b,c) ->
+    let p = F.p_bool c in
+    let q = F.p_not p in
+    fd#set_title "Compute (split)" ;
+    fd#set_descr "Split on if-then-else condition" ;
+    Applicable (Tactical.rewrite ?at ["If-Then",p,e,a;"If-Else",q,e,b])
+  | Unfold(e,f,d) ->
+    fd#set_title "Compute (def)" ;
+    fd#set_descr "Unfold definition of '%s'" (Lang.name_of_lfun f) ;
+    Applicable (Tactical.rewrite ?at ["Definition",F.p_true,e,d])
+
+class compute : Tactical.tactical =
+  object
+    inherit Tactical.make ~id:"Wp.compute"
+        ~title:"Compute"
+        ~descr:"Unfold definitions and split on conditions"
+        ~params:[]
+    method select feedback (s : Tactical.selection) =
+      process feedback ?at:(Tactical.at s) (Tactical.selected s)
+  end
+
+let tactical = Tactical.export (new compute)
+let strategy = Strategy.make tactical ~arguments:[]
+
+(* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/wp/TacCompute.mli b/src/plugins/wp/TacCompute.mli
new file mode 100644
index 0000000000000000000000000000000000000000..40e616729898b7aba4ab65ce386e7c6f81ed8f19
--- /dev/null
+++ b/src/plugins/wp/TacCompute.mli
@@ -0,0 +1,31 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of WP plug-in of Frama-C.                           *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2023                                               *)
+(*    CEA (Commissariat a l'energie atomique et aux energies              *)
+(*         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).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Built-in Compute Tactical (auto-registered) *)
+
+open Tactical
+open Strategy
+
+val tactical : tactical
+val strategy : ?priority:float -> selection -> strategy
+
+(**************************************************************************)
diff --git a/src/plugins/wp/TacUnfold.ml b/src/plugins/wp/TacUnfold.ml
index dc09597c76a7ef1d1f61257fd306548e112aded8..588d32aaa93d789c2a6f5de7e8619fd75b485378 100644
--- a/src/plugins/wp/TacUnfold.ml
+++ b/src/plugins/wp/TacUnfold.ml
@@ -49,6 +49,9 @@ let range f es =
       (F.p_leq e (F.e_zint b)) in
   F.e_prop (F.p_all range es)
 
+let unfold f es =
+  try definition f es with Not_found -> range f es
+
 (* Used only for non Multi selection *)
 
 let rec applicable ?at e f es = function
diff --git a/src/plugins/wp/TacUnfold.mli b/src/plugins/wp/TacUnfold.mli
index 10e556d6405aa1680b2216975e8443a57b170631..ac7a5aefe7ffafddc3a45245e9a4ea40daf2cf99 100644
--- a/src/plugins/wp/TacUnfold.mli
+++ b/src/plugins/wp/TacUnfold.mli
@@ -25,6 +25,9 @@
 open Tactical
 open Strategy
 
+(** @raises Not_found *)
+val unfold : Lang.lfun -> Lang.F.term list -> Lang.F.term
+
 val tactical : tactical
 val strategy : ?priority:float -> selection -> strategy
 
diff --git a/src/plugins/wp/Tactical.ml b/src/plugins/wp/Tactical.ml
index 4d064d09b693fe222efa45e5ac0281c0946b59cf..08cb1f3e2270b19ba36166ddb4bccbc5b00eeb7d 100644
--- a/src/plugins/wp/Tactical.ml
+++ b/src/plugins/wp/Tactical.ml
@@ -24,13 +24,13 @@ open Conditions
 open Lang.F
 
 module Tmap = Map.Make(String)
-let composers = ref Tmap.empty
-let groups = ref []
 
 (* -------------------------------------------------------------------------- *)
 (* --- Composer Factory                                                   --- *)
 (* -------------------------------------------------------------------------- *)
 
+type computer = term list -> term
+
 class type composer =
   object
     method id : string
@@ -42,6 +42,10 @@ class type composer =
     method compute : term list -> term
   end
 
+let computers : computer Tmap.t ref = ref Tmap.empty
+let composers : composer Tmap.t ref = ref Tmap.empty
+let groups = ref []
+
 let rec insert_group cc = function
   | [] -> [cc#group , [cc]]
   | (( gid , ccs ) as group ):: others ->
@@ -50,12 +54,17 @@ let rec insert_group cc = function
     else
       group :: insert_group cc others
 
+let add_computer id cc =
+  if not (Tmap.mem id !computers) then
+    computers := Tmap.add id cc !computers
+
 let add_composer (c : #composer) =
   let id = c#id in
-  if Tmap.mem id !composers then
+  if Tmap.mem id !composers || Tmap.mem id !computers then
     Wp_parameters.error "Composer #%s already registered (skipped)" id
   else
     begin
+      computers := Tmap.add id (c#compute :> computer) !computers ;
       composers := Tmap.add id (c :> composer) !composers ;
       groups := insert_group (c :> composer) !groups ;
     end
@@ -143,7 +152,15 @@ let get_int = function
   | Compose(Cint a) -> get_int_z a
   | s ->
     match Lang.F.repr (selected s) with
-    | Qed.Logic.Kint z -> get_int_z z
+    | Kint z -> get_int_z z
+    | _ -> None
+
+let get_bool = function
+  | Empty -> None
+  | s ->
+    match Lang.F.repr (selected s) with
+    | True -> Some true
+    | False -> Some false
     | _ -> None
 
 let subclause clause p =
@@ -187,8 +204,8 @@ let cint a = Compose(Cint a)
 let range a b = Compose(Range(a,b))
 let compose id es =
   try
-    let cc = Tmap.find id !composers in
-    let e = cc#compute (List.map selected es) in
+    let cc = Tmap.find id !computers in
+    let e = cc (List.map selected es) in
     match Lang.F.repr e with
     | Qed.Logic.Kint n -> cint n
     | _ -> Compose(Code(e,id,es))
@@ -308,14 +325,6 @@ type parameter =
   | Selector : 'a field * 'a named list * ('a -> 'a -> bool) -> parameter
   | Search : 'a named option field * 'a browser * 'a finder -> parameter
 
-let param = function
-  | Checkbox{ vid }
-  | Spinner({vid},_)
-  | Composer({vid},_)
-  | Selector({vid},_,_)
-  | Search({vid},_,_)
-    -> vid
-
 let checkbox ~id ~title ~descr ?(default=false) () =
   let fd = field ~id ~title ~descr ~default in
   fd , Checkbox fd
@@ -353,6 +362,13 @@ let search ~id ~title ~descr ~browse ~find () =
   let fd = field ~id ~title ~descr ~default:None in
   fd , Search(fd,browse,find)
 
+let pident = function
+  | Checkbox fd -> ident fd
+  | Spinner(fd,_) -> ident fd
+  | Composer(fd,_) -> ident fd
+  | Selector(fd,_,_) -> ident fd
+  | Search(fd,_,_) -> ident fd
+
 (* -------------------------------------------------------------------------- *)
 (* --- Feedback                                                           --- *)
 (* -------------------------------------------------------------------------- *)
@@ -426,8 +442,11 @@ let rewrite ?at patterns sequent =
          Conditions.subst
            (fun e -> if e == src then tgt else raise Not_found)
            sequent in
-       let step = Conditions.(step ~descr (When guard)) in
-       descr , Conditions.insert ?at step sequent
+       let sequent =
+         if Lang.F.eqp Lang.F.p_true guard then sequent else
+           let step = Conditions.(step ~descr (When guard)) in
+           Conditions.insert ?at step sequent
+       in descr , sequent
     ) patterns
 
 let condition name guard process seq =
@@ -485,7 +504,7 @@ let export t = register t ; (t :> t)
 let iter f = Tmap.iter (fun _id t -> f t) !tacticals
 let lookup ~id = Tmap.find id !tacticals
 let lookup_param tactic ~id =
-  List.find (fun p -> param p = id) tactic#params
+  List.find (fun p -> pident p = id) tactic#params
 
 (* -------------------------------------------------------------------------- *)
 (* --- Default Composers                                                  --- *)
@@ -493,6 +512,13 @@ let lookup_param tactic ~id =
 
 open Lang
 
+let () = add_computer "wp:true" (fun _ -> e_true)
+let () = add_computer "wp:false" (fun _ -> e_false)
+let () = add_computer "wp:list" Vlist.list
+let () = add_computer "wp:concat" Vlist.concat
+let () = add_computer "wp:repeat"
+    (function [a;n] -> Vlist.repeat a n | _ -> raise Not_found)
+
 let () =
   for i = 0 to 9 do
     add_composer
@@ -525,6 +551,24 @@ let () = add_composer
       method compute = function [a;b] -> F.e_eq a b | _ -> F.e_true
     end)
 
+let () = add_composer
+    (object
+      method id = "wp:neq"
+      method group = "logic"
+      method title = "A != B"
+      method descr = ""
+      method arity = 2
+      method filter = function
+        | [a;b] ->
+          (try
+             let ta = F.typeof a in
+             let tb = F.typeof b in
+             F.Tau.equal ta tb
+           with Not_found -> false)
+        | _ -> false
+      method compute = function [a;b] -> F.e_neq a b | _ -> F.e_false
+    end)
+
 let () = add_composer
     (object
       method id = "wp:leq"
diff --git a/src/plugins/wp/Tactical.mli b/src/plugins/wp/Tactical.mli
index 57b517083452d50d3b6cb8815eeffe23c81ed919..f313adde10789845b814992fcbdcc7cbc1d70e86 100644
--- a/src/plugins/wp/Tactical.mli
+++ b/src/plugins/wp/Tactical.mli
@@ -54,6 +54,7 @@ val range : int -> int -> selection
 val compose : string -> selection list -> selection
 val multi : selection list -> selection
 val get_int : selection -> int option
+val get_bool : selection -> bool option
 val destruct : selection -> selection list
 
 val head : clause -> pred
@@ -101,7 +102,7 @@ type parameter =
 val ident : 'a field -> string
 val default : 'a field -> 'a
 val signature : 'a field -> 'a named
-val param : parameter -> string
+val pident : parameter -> string
 
 val checkbox :
   id:string -> title:string -> descr:string ->
@@ -261,5 +262,7 @@ val iter : (tactical -> unit) -> unit
 val lookup : id:string -> tactical
 val lookup_param : tactical -> id:string -> parameter
 
+type computer = term list -> term
+val add_computer : string -> computer -> unit
 val add_composer : #composer -> unit
 val iter_composer : (composer -> unit) -> unit
diff --git a/src/plugins/wp/VCS.ml b/src/plugins/wp/VCS.ml
index ca000ced16280f15aba38e639191a32204a575b0..e4b0d5f91ee8baa7568ceed61c3eb824b57ce482 100644
--- a/src/plugins/wp/VCS.ml
+++ b/src/plugins/wp/VCS.ml
@@ -140,6 +140,11 @@ let cmp_prover p q =
 let pp_prover fmt p = Format.pp_print_string fmt (title_of_prover p)
 let pp_mode fmt m = Format.pp_print_string fmt (title_of_mode m)
 
+let provers () =
+  List.map (fun p -> Why3 p) @@
+  List.filter Why3Provers.is_mainstream @@
+  Why3Provers.provers ()
+
 module P = struct type t = prover let compare = cmp_prover end
 module Pset = Set.Make(P)
 module Pmap = Map.Make(P)
@@ -150,28 +155,31 @@ module Pmap = Map.Make(P)
 
 type config = {
   valid : bool ;
-  timeout : int option ;
+  timeout : float option ;
   stepout : int option ;
 }
 
-let param f = let v = f() in if v>0 then Some v else None
-
-let current () = {
-  valid = false ;
-  timeout = param Wp_parameters.Timeout.get ;
-  stepout = param Wp_parameters.Steps.get ;
-}
+let current () =
+  let t = Wp_parameters.Timeout.get () in
+  let s = Wp_parameters.Steps.get () in
+  {
+    valid = false ;
+    timeout = if t > 0 then Some (float t) else None ;
+    stepout = if s > 0 then Some s else None ;
+  }
 
 let default = { valid = false ; timeout = None ; stepout = None }
 
 let get_timeout ?kf ~smoke = function
   | { timeout = None } ->
     if smoke
-    then Wp_parameters.SmokeTimeout.get ()
-    else begin match Option.map Wp_parameters.FctTimeout.find kf with
-      | exception Not_found | None -> Wp_parameters.Timeout.get ()
-      | Some timeout -> timeout
-    end
+    then float @@ Wp_parameters.SmokeTimeout.get ()
+    else
+      let t =
+        match Option.map Wp_parameters.FctTimeout.find kf with
+        | None | exception Not_found -> Wp_parameters.Timeout.get ()
+        | Some timeout -> timeout
+      in float t
   | { timeout = Some t } -> t
 
 let get_stepout = function
@@ -226,14 +234,14 @@ let configure r =
   let timeout =
     let t = r.prover_time in
     if t > 0.0 then
-      let timeout = Wp_parameters.Timeout.get() in
-      let margin = Wp_parameters.TimeExtra.get() + int_of_float (t +. 0.5) in
-      Some(max timeout margin)
+      let timeout = float @@ max 0 @@ Wp_parameters.Timeout.get() in
+      let margin = float @@ max 0 @@ Wp_parameters.TimeExtra.get () in
+      Some(timeout +. margin)
     else
       None in
   let stepout =
     if r.prover_steps > 0 && r.prover_time <= 0.0 then
-      let stepout = Wp_parameters.Steps.get () in
+      let stepout = max 0 @@ Wp_parameters.Steps.get () in
       let margin = 1000 in
       Some(max stepout margin)
     else None in
@@ -274,7 +282,7 @@ let no_result = result NoResult
 let valid = result Valid
 let invalid = result Invalid
 let unknown = result Unknown
-let timeout t = result ~time:(float t) Timeout
+let timeout t = result ~time:t Timeout
 let stepout n = result ~steps:n Stepout
 let computing kill = result (Computing kill)
 let failed ?pos msg = {
diff --git a/src/plugins/wp/VCS.mli b/src/plugins/wp/VCS.mli
index 29098111ebd50b50a89f9a8723d8d4440768b5de..f5ecae0ad98af6fd9801480d86414028ac29c025 100644
--- a/src/plugins/wp/VCS.mli
+++ b/src/plugins/wp/VCS.mli
@@ -41,6 +41,9 @@ type mode =
 module Pset : Set.S with type elt = prover
 module Pmap : Map.S with type key = prover
 
+(** Mainstream installed provers *)
+val provers : unit -> prover list
+
 val name_of_prover : prover -> string
 val title_of_prover : ?version:bool -> prover -> string
 val filename_for_prover : prover -> string
@@ -62,7 +65,7 @@ val cmp_prover : prover -> prover -> int
 
 type config = {
   valid : bool ;
-  timeout : int option ;
+  timeout : float option ;
   stepout : int option ;
 }
 
@@ -70,8 +73,8 @@ val current : unit -> config (** Current parameters *)
 
 val default : config (** all None *)
 
-val get_timeout : ?kf:Kernel_function.t -> smoke:bool -> config -> int
-(** 0 means no-timeout *)
+val get_timeout : ?kf:Kernel_function.t -> smoke:bool -> config -> float
+(** 0.0 means no-timeout *)
 
 val get_stepout : config -> int (** 0 means no-stepout *)
 
@@ -102,7 +105,7 @@ val valid : result
 val invalid : result
 val unknown : result
 val stepout : int -> result
-val timeout : int -> result
+val timeout : float -> result
 val computing : (unit -> unit) -> result
 val failed : ?pos:Lexing.position -> string -> result
 val kfailed : ?pos:Lexing.position -> ('a,Format.formatter,unit,result) format4 -> 'a
diff --git a/src/plugins/wp/Vlist.ml b/src/plugins/wp/Vlist.ml
index 0673d24fb816bef8a16b0768963a7e7579fe7579..05f905cc0cde2cfbed4389c36ca1782a9a4a648a 100644
--- a/src/plugins/wp/Vlist.ml
+++ b/src/plugins/wp/Vlist.ml
@@ -51,6 +51,8 @@ let l_repeat = E.(F_call "repeat")
 let () = LogicBuiltins.add_type t_list ~library ~link:l_list ()
 let a_list = Lang.get_builtin_type ~name:t_list
 
+let alist e = L.Data(a_list,[e])
+
 let vlist_get_tau = function
   | None -> invalid_arg "a list operator without result type"
   | Some t -> t
@@ -63,11 +65,11 @@ let ty_listelt = function
 
 let ty_cons = function
   | [ _ ; Some l ] -> l
-  | [ Some e ; _ ] -> L.Data(a_list,[e])
+  | [ Some e ; _ ] -> alist e
   | _ -> raise Not_found
 
 let ty_elt = function
-  | [ Some e ] -> L.Data(a_list,[e])
+  | [ Some e ] -> alist e
   | _ -> raise Not_found
 
 let ty_nth = function
@@ -149,6 +151,14 @@ let v_concat es tau = F.e_fun f_concat es ~result:tau
 let v_length l = F.e_fun f_length [l]
 let v_repeat s n tau = F.e_fun f_repeat [s;n] ~result:tau
 
+let concat vs =
+  let tl = Lang.F.typeof (List.hd vs) in
+  v_concat vs tl
+
+let list es = concat (List.map v_elt es)
+
+let repeat s n = v_repeat s n (Lang.F.typeof s)
+
 (* -------------------------------------------------------------------------- *)
 (* --- Rewriters                                                          --- *)
 (* -------------------------------------------------------------------------- *)
@@ -480,6 +490,10 @@ let check_term e =
     | _ -> false
   with Not_found -> false
 
+let elist (t : tau) =
+  match t with
+  | L.Data(_,[e]) when check_tau t -> Some e
+  | _ -> None
 
 let f_vlist_eq = Lang.extern_f ~library ~sort:L.Sprop "vlist_eq"
 
@@ -545,10 +559,10 @@ let rec collect xs = function
       | _ -> List.rev xs , w
     end
 
-let list engine fmt xs = Qed.Plib.pp_listsep ~sep:"," engine#pp_flow fmt xs
+let pplist engine fmt xs = Qed.Plib.pp_listsep ~sep:"," engine#pp_flow fmt xs
 
 let elements (engine : #engine) fmt xs =
-  Format.fprintf fmt "@[<hov 2>[ %a ]@]" (list engine) xs
+  Format.fprintf fmt "@[<hov 2>[ %a ]@]" (pplist engine) xs
 
 let rec pp_concat (engine : #engine) fmt es =
   let xs , es = collect [] es in
@@ -569,7 +583,7 @@ let pretty (engine : #engine) fmt es =
 
 let pprepeat (engine : #engine) fmt = function
   | [l;n] -> Format.fprintf fmt "@[<hov 2>(%a *^@ %a)@]" engine#pp_flow l engine#pp_flow n
-  | es -> Format.fprintf fmt "@[<hov 2>repeat(%a)@]" (list engine) es
+  | es -> Format.fprintf fmt "@[<hov 2>repeat(%a)@]" (pplist engine) es
 
 let shareable e =
   match F.repr e with
diff --git a/src/plugins/wp/Vlist.mli b/src/plugins/wp/Vlist.mli
index 85106e3192f96fbd29c0bcb81e6d56d58daa2c2f..2074985d3459982939348331ac881a72d7ed6599 100644
--- a/src/plugins/wp/Vlist.mli
+++ b/src/plugins/wp/Vlist.mli
@@ -28,6 +28,8 @@ open Lang
 
 val check_tau : tau -> bool
 val check_term : F.term -> bool
+val alist : tau -> tau (* element -> list of element *)
+val elist : tau -> tau option (* list -> element *)
 
 class type engine =
   object
@@ -43,6 +45,10 @@ val f_cons : Fun.t
 val f_concat : Fun.t
 val f_repeat : Fun.t
 
+val list : F.term list -> F.term
+val concat : F.term list -> F.term
+val repeat : F.term -> F.term -> F.term
+
 val export : #engine -> Format.formatter -> F.term list -> unit
 val pretty : #engine -> Format.formatter -> F.term list -> unit
 val elements : #engine -> Format.formatter -> F.term list -> unit
diff --git a/src/plugins/wp/WpTac.ml b/src/plugins/wp/WpTac.ml
index 65ac410e6444673719c15da7799f3d4c0486f2fb..6c33b85936cae84d7e39772c6532bd3f4489a7b8 100644
--- a/src/plugins/wp/WpTac.ml
+++ b/src/plugins/wp/WpTac.ml
@@ -371,7 +371,7 @@ let e_dnf = cnf_dnf ~pol:false
 
 (* feature at Conditions.closure and also for debugging purposes *)
 let () = Conditions.at_closure (fun ((step,goal) as sequent) ->
-    match Wp_parameters.SplitDepth.get () with
+    match Wp_parameters.SplitCNF.get () with
     | 0 ->  sequent
     | depth when depth < -1  ->
       (* Unspecified debug mode checking the correctness of CNF algo:
diff --git a/src/plugins/wp/cfgAnnot.ml b/src/plugins/wp/cfgAnnot.ml
index b06baf97c1cfac7aeb5ab70538446143bdfa1ca7..5eb9442a2b603221781c6716b14af5620a0c5355 100644
--- a/src/plugins/wp/cfgAnnot.ml
+++ b/src/plugins/wp/cfgAnnot.ml
@@ -59,8 +59,7 @@ type behavior = {
 
 let normalize_assumes h =
   let module L = NormAtLabels in
-  let labels = L.labels_fct_pre in
-  L.preproc_annot labels h
+  L.preproc_annot L.labels_fct_pre h
 
 let implies ?assumes p =
   match assumes with None -> p | Some h -> Logic_const.pimplies (h,p)
@@ -77,7 +76,8 @@ let normalize_pre ~goal kf bhv ?assumes ip =
     let id = WpPropId.mk_pre_id kf Kglobal bhv ip in
     let pre = ip.ip_content.tp_statement in
     let assumes = Option.map normalize_assumes assumes in
-    Some (id, L.preproc_annot labels @@ implies ?assumes pre)
+    let precond = L.preproc_annot labels pre in
+    Some (id, implies ?assumes precond)
   else None
 
 let normalize_post ~goal kf bhv tk ?assumes (itk,ip) =
@@ -87,8 +87,8 @@ let normalize_post ~goal kf bhv tk ?assumes (itk,ip) =
     let assumes = Option.map (fun p -> normalize_assumes @@ at_pre p) assumes in
     let labels = L.labels_fct_post ~exit:(tk=Exits) in
     let id = WpPropId.mk_post_id kf Kglobal bhv (tk,ip) in
-    let p = L.preproc_annot labels ip.ip_content.tp_statement in
-    Some (id , implies ?assumes p)
+    let post = L.preproc_annot labels ip.ip_content.tp_statement in
+    Some (id , implies ?assumes post)
   else None
 
 let normalize_decreases (d, li) =
@@ -464,7 +464,7 @@ module CodeAssertions = WpContext.StaticGenerator(CodeKey)
 
 let get_code_assertions ?(smoking=false) kf stmt =
   let ca = CodeAssertions.get (kf,stmt) in
-  (* Make sur that smoke tests are in the end so that it can see surely false
+  (* Make sure that smoke tests are in the end so that it can see surely false
      assertions associated to this statement, in particular RTE assertions.   *)
   List.rev @@
   if smoking then
@@ -607,20 +607,22 @@ module LoopContract = WpContext.StaticGenerator(CodeKey)
     end)
 
 let get_loop_contract ?(smoking=false) ?terminates kf stmt =
+  (* Loop Contract *)
   let lc = LoopContract.get (kf,stmt) in
-  let lc_smoke = if smoking && not (WpReached.is_dead_code stmt) then
+  (* Loop Smoking *)
+  let lc =
+    if smoking && not (WpReached.is_dead_code stmt) then
       let g = smoke kf ~id:"dead_loop" ~unreachable:stmt () in
       { lc with loop_smoke = g :: lc.loop_smoke }
     else lc
   in
-  match lc_smoke.loop_terminates, terminates with
-  | None, _ ->
-    lc_smoke
-  | Some _, None ->
-    { lc_smoke with loop_terminates = None }
+  (* Loop Termination *)
+  match lc.loop_terminates, terminates with
+  | None, _ -> lc
+  | Some _, None -> { lc with loop_terminates = None }
   | Some loop_terminates, Some terminates ->
     let prop = Logic_const.pimplies(terminates, loop_terminates) in
-    { lc_smoke with loop_terminates = Some prop }
+    { lc with loop_terminates = Some prop }
 
 (* -------------------------------------------------------------------------- *)
 (* --- Clear Tablesnts                                                    --- *)
diff --git a/src/plugins/wp/cfgCalculus.ml b/src/plugins/wp/cfgCalculus.ml
index a57a8c1c06971d053fa9d0b4ed8c192644f50d51..d5c81fc3a8f8cc73ac000dc3f387b87a496ed1f3 100644
--- a/src/plugins/wp/cfgCalculus.ml
+++ b/src/plugins/wp/cfgCalculus.ml
@@ -219,8 +219,7 @@ struct
     let kl = Cil.CurrentLoc.get () in
     try
       Cil.CurrentLoc.set (Stmt.loc s) ;
-      let smoking =
-        is_default_bhv env.mode && env.dead s in
+      let smoking = is_default_bhv env.mode && env.dead s in
       let cas = CfgAnnot.get_code_assertions ~smoking env.mode.kf s in
       let opt_fold f = Option.fold ~none:Fun.id ~some:f in
       let do_assert env CfgAnnot.{ code_admitted ; code_verified } w =
diff --git a/src/plugins/wp/cfgInfos.ml b/src/plugins/wp/cfgInfos.ml
index a24e5e48c2ec87eec13edb2ab073939f1efea6cd..b2da833c128c9d7f53688d0c0988cb167a440607 100644
--- a/src/plugins/wp/cfgInfos.ml
+++ b/src/plugins/wp/cfgInfos.ml
@@ -52,10 +52,11 @@ let calls infos = infos.calls
 let annots infos = infos.annots
 let doomed infos = infos.doomed
 
-let wpreached s = function
+let wp_reached_smoking s = function
   | None -> false
   | Some reachability -> WpReached.smoking reachability s
-let smoking infos s = wpreached s infos.reachability
+
+let smoking infos s = wp_reached_smoking s infos.reachability
 
 let unreachable infos v =
   match infos.body, infos.checkpath with
@@ -457,7 +458,7 @@ let compile Key.{ kf ; smoking ; bhv ; prop } =
            let loop_pids = loop_contract_pids kf stmt in
            if dead then
              begin
-               if wpreached stmt reachability then
+               if wp_reached_smoking stmt reachability then
                  (let p = CfgAnnot.get_unreachable kf stmt in
                   infos.doomed <- Bag.append infos.doomed p) ;
                infos.doomed <- Bag.concat infos.doomed (Bag.list ca_pids) ;
diff --git a/src/plugins/wp/cfgWP.ml b/src/plugins/wp/cfgWP.ml
index 096f49bb1336ec56d905cf2d770d86560b59b690..2e20c87f609994abbe5ea888efda2b9009527081 100644
--- a/src/plugins/wp/cfgWP.ml
+++ b/src/plugins/wp/cfgWP.ml
@@ -859,9 +859,9 @@ struct
   let condition ~descr ?stmt ?warn pa h vc =
     passify_vc pa (assume_vc ?stmt ?warn ~descr h vc)
 
-  let mark ?(smoke=false) m = function
+  let split_branch ~smoke tag = function
     | None -> Splitter.empty
-    | Some s -> if smoke then s else Splitter.group m merge_vcs s
+    | Some s -> if smoke then s else Splitter.apply tag merge_vcs s
 
   let random () =
     let v = Lang.freshvar ~basename:"cond" Logic.Bool in
@@ -883,7 +883,7 @@ struct
          in
          let effects = Eset.union wp1.effects wp2.effects in
          let dosplit =
-           Wp_parameters.Split.get () &&
+           Wp_parameters.SplitBranch.get () &&
            let n1 = weight wp1.vcs in
            let n2 = weight wp2.vcs in
            let nm = Wp_parameters.SplitMax.get () in
@@ -898,8 +898,8 @@ struct
              Gmap.merge
                (fun g w1 w2 ->
                   let smoke = TARGET.is_smoke_test g in
-                  let s1 = mark ~smoke (Splitter.if_then stmt) w1 in
-                  let s2 = mark ~smoke (Splitter.if_else stmt) w2 in
+                  let s1 = split_branch ~smoke (Splitter.if_then stmt) w1 in
+                  let s2 = split_branch ~smoke (Splitter.if_else stmt) w2 in
                   Some (Splitter.union (merge_vc) s1 s2)
                ) vcs1 vcs2
            else
@@ -918,7 +918,7 @@ struct
   (* -------------------------------------------------------------------------- *)
 
   let rec cc_case_values ks vs sigma = function
-    | [] -> ks , vs
+    | [] -> List.rev ks , List.rev vs
     | e::es ->
       match Ctypes.get_int64 e with
       | Some k ->
@@ -927,11 +927,16 @@ struct
         cc_case_values ks (C.val_of_exp sigma e::vs) sigma es
 
   let cc_group_case stmt warn descr tag pa cond vcs : vc Splitter.t Gmap.t =
-    Gmap.map
-      (fun s ->
+    let split =
+      Wp_parameters.SplitSwitch.get () &&
+      weight vcs < Wp_parameters.SplitMax.get ()
+    in
+    Gmap.mapi
+      (fun g s ->
+         let smoke = TARGET.is_smoke_test g in
          Splitter.map
            (condition ~descr ~warn ~stmt pa cond)
-           (Splitter.group tag merge_vcs s)
+           (if smoke || not split then s else Splitter.apply tag merge_vcs s)
       ) vcs
 
   let cc_case stmt warn sigma v (es,wp) =
@@ -971,7 +976,7 @@ struct
          let vcs_cases = List.map (cc_case stmt warn sigma value) cases in
          let neq = List.map (fun (vs,_) -> p_all (p_neq value) vs) vcs_cases in
          let vcs_default = cc_default stmt sigma neq default in
-         let vcs = merge_all_vcs ( vcs_default :: List.map snd vcs_cases ) in
+         let vcs = merge_all_vcs ( vcs_default :: List.rev_map snd vcs_cases ) in
          let effects = List.fold_left
              (fun es (_,wp) -> Eset.union es wp.effects)
              default.effects cases in
@@ -1041,7 +1046,7 @@ struct
       (fun s ->
          Splitter.map
            (fun vc -> passify_vc pa (instance_of vc))
-           (Splitter.group tag merge_vcs s)
+           (Splitter.apply tag merge_vcs s)
       ) wp.vcs
 
   let call_dynamic wenv stmt gpid fct calls = L.in_frame wenv.frame
@@ -1525,7 +1530,7 @@ struct
     let hyps = Conditions.bundle vc.hyps in
     let goal g = { vcq with VC_Annot.goal = GOAL.make (hyps,g) } in
     match F.p_expr vc.goal with
-    | Logic.And gs when Wp_parameters.Split.get () -> Bag.list (List.map goal gs)
+    | Logic.And gs when Wp_parameters.SplitConj.get () -> Bag.list (List.map goal gs)
     | _ -> Bag.elt (goal vc.goal)
 
   let make_trivial vc =
diff --git a/src/plugins/wp/doc/manual/wp_plugin.tex b/src/plugins/wp/doc/manual/wp_plugin.tex
index 14c71ecce55c800cae91fe75fe0c123d0d9a3b1d..4f31910e4a20419e5b56ef1609ab009ea5b3bcb9 100644
--- a/src/plugins/wp/doc/manual/wp_plugin.tex
+++ b/src/plugins/wp/doc/manual/wp_plugin.tex
@@ -272,7 +272,10 @@ for marking, the option \verb+-wp-finalize-scripts+ can be used to remove all
 orphan scripts and the marking directory. The option \verb+-wp-dry-finalize-scripts+
 can be used to log the remove actions instead of actually doing them.
 
-\subsection{Strategies}
+\subsection{Strategies (DEPRECATED)}
+
+\paragraph[Warning:] Strategies described below are \emph{deprecated} since Frama-C 27.0 (Cobalt).
+Please use ``Proof Strategies'' instead (Section~\ref{wp-proof-strategies}).
 
 Strategies are heuristics that generate a prioritized bunch of tactics to be tried on the current goal.
 Few built-in strategies are provided by the \textsf{WP} plug-in ; however, the user can extends the proof editor with
@@ -304,8 +307,12 @@ The name of registered strategies is printed on console by using \texttt{-wp-aut
 
 \subsection{General Tactics}
 
-\paragraph{Absurd} Contradict a Hypothesis\\
-The user can select a hypothesis $H$, and change the goal to $\neg H$:
+\paragraph{Absurd} Contradict the Goal or an Hypothesis\\
+The user can prove the goal by contradiction:
+
+$$ \TACTIC{\Delta\models\,G}{\Delta,\neg G\models\,\mathtt{false}} $$
+
+Or the user can select a hypothesis $H$, and change the goal to $\neg H$:
 
 $$ \TACTIC{\Delta,H\models\,G}{\Delta\models\,\neg H} $$
 
@@ -865,12 +872,16 @@ interface of the programmatic API.
     \texttt{@decreases},
     \texttt{\mbox{@complete\_behaviors}}, \texttt{\mbox{@disjoint\_behaviors}}.
     \\
-    Properties can be prefixed with a minus sign to \emph{skip} the associated annotations.
+    Tags and categories can be prefixed with a minus sign to \emph{skip}
+    the associated annotations.
     For example \texttt{-wp-prop="-@assigns"} removes all \texttt{assigns}
     and \texttt{loop assigns} properties from the selection.
     \\
-    \textbf{Remark:} properties with name \verb+no_wp:+ are always and automatically
-    filtered and never proved by \textsf{WP}.
+    Tag names also include the name of the function or
+    lemma associated with the property.
+    \\
+    \textbf{Remark:} properties with tag name \verb+no_wp:+ are always and automatically
+    filtered out and never proved by \textsf{WP}.
 \item [\tt -wp-(no)-status-all] includes in the goal selection all properties
   regardless of their current status (default is: \texttt{no}).
 \item [\tt -wp-(no)-status-valid] includes in the goal selection those properties
@@ -1014,14 +1025,16 @@ weakest precondition calculus.
   Refer to Section~\ref{wp-model-arith} for details.
 \item[\tt -wp-(no)-init-const] use initializers for global const variables
   (defaut is: \texttt{yes}).
-\item[\tt -wp-(no)-split] conjunctions in generated proof obligations are
+\item[\tt -wp-(no)-split] Splits conditional statements into separated goals (default is: \texttt{no}).
+\item[\tt -wp-(no)-split-switch] Splits switch statements into sepeared goals (default is: \texttt{yes}).
+\item[\tt -wp-split-max <{\it n}>]
+  limits the number of sub-goals generated by  \verb|-wp-split| and \verb|-wp-split-switch|
+  (defaults to \verb+1000+).
+\item[\tt -wp-(no)-split-conj] conjunctions in generated proof obligations are
   recursively split into sub-goals.  The generated goal names are
   suffixed by ``{\tt part<{\it n}>}'' (defaults to \texttt{no}).
-\item[\tt -wp-split-depth <{\it d}>] sets the depth of exploration for the
-  \texttt{-wp-split} option. ``-1'' stands for unlimited depth. Default is 0.
-\item[\tt -wp-split-max <{\it n}>] When \verb+-wp-split+ is active,
-  limit the number of generated sub-goals to \textit{n} parts on each conditional statement.
-  (defaults to \verb+1000+).
+\item[\tt -wp-split-cnf <{\it d}>] transforms all goals with in conjunctive normal form (CNF) at depth {\tt\it d}.
+  Value \verb|-1| stands for unlimited depth. Default is 0, which means no CNF transformation.
 \item[\tt -wp-(no)-callee-precond] includes preconditions of the callee
   after\footnote{Proof obligations are always generated to check preconditions.}
   a call (default is: \texttt{yes}).
@@ -1301,6 +1314,21 @@ See \texttt{-wp-interactive <mode>} option for details.
   It is possible to ask for several decision procedures to be tried.
   For each goal, the first decision procedure that succeeds cancels the
   other attempts.
+
+  You may also select provers \verb|"tip"| to use proof strategies and \verb|"script"| to use
+  proof scripts (without applying new proof strategies),
+  see option \verb|"-wp-script"| below for more details.
+\item[\tt -wp-script <mode>] selects how to manage proof strategies and proof
+  scripts session. Several modes are available:
+  \begin{itemize}
+  \item \texttt{"batch"} use existing scripts, but do not store new scripts.
+    This is the default mode for prover \verb|"script"|.
+  \item \texttt{"update"} use existing scripts and store new or updated scripts in proof session.
+    This is the default mode for prover \verb|tip|.
+  \item \texttt{"init"} don't use existing scripts and store the newly generated
+    scripts in proof session.
+  \item \texttt{"dry"} don't use existing script and don't store any new scripts in proof session.
+  \end{itemize}
 \item[\tt -wp-interactive <mode>] selects the interaction mode with
   interactive provers such as Coq (while it could work for other interactive
   provers, it has not been tested so far). Five modes are available:
@@ -1313,6 +1341,8 @@ See \texttt{-wp-interactive <mode>} option for details.
   \end{itemize}
   New scripts are created in the \texttt{interactive} directory of \textsf{WP}
   session (see option \texttt{-wp-session <dir>}).
+  In case option \verb|-wp-cache-env| is set, the script mode is taken from environment
+  variable \verb|FRAMAC_WP_SCRIPT| instead.
 \item[\tt -wp-detect] lists the provers available for \textsf{Why-3}.
   This command can only work if \textsf{why3} API was installed before building and
   installing \textsf{Frama-C}.
@@ -1321,6 +1351,8 @@ See \texttt{-wp-interactive <mode>} option for details.
 \item[\tt -wp-(no)-run-all-provers] Run all specified provers on each goal not
   proved by Qed. When a prover succeeds in proving the goal, the others are not
   stopped. (default is: no).
+\item[\tt -wp-strategy s,...] specifies the default
+  ones to be used, see Section~\ref{wp-proof-strategies} for details.
 \item[\tt -wp-gen] only generates proof obligations, does not run provers.
   See option \texttt{-wp-out} to obtain the generated proof obligations.
 \item[\tt -wp-par <n>] limits the number of parallel process runs for
@@ -1335,12 +1367,10 @@ See \texttt{-wp-interactive <mode>} option for details.
 \item[\tt -wp-(no)-proof-trace] asks for provers to output extra information
   on proved goals when available (default is: \texttt{no}).
 \item[\tt -wp-timeout <n>] sets the timeout (in seconds) for the calls
-  to the decision prover (defaults to 10 seconds).
+  to the decision prover (defaults to 2 seconds).
 \item[\tt -wp-fct-timeout <f1:t1,f2:t2,...>] customize the timeout for each
   specified function (\texttt{t1} for \texttt{f1}, \texttt{t2} for \texttt{f2},
   etc).
-\item[\tt -wp-smoke-timeout <n>] sets the timeout (in seconds) for smoke tests
-  (see \verb+-wp-smoke-tests+, defaults to 5 seconds).
 \item[\tt -wp-interactive-timeout <n>] sets the timeout (in seconds) for checking
   edited scripts with interactive provers (defaults to 30 seconds).
 \item[\tt -wp-(no)-script-on-stdout] displays generated proof scripts on stdout
@@ -1420,9 +1450,12 @@ removed when \textsf{Frama-C} exits.
 Other options controlling the output of generated proof
 obligations are:
 \begin{description}
-\item[\tt -wp-(no)-print] pretty-prints the generated proof obligations on
+\item[\tt -wp-print] pretty-prints the generated proof obligations on
   the standard output. Results obtained by provers are reported as
-  well (default is: \texttt{no}).
+  well.
+\item[\tt -wp-status] pretty-prints only proof obligations that are not (yet)
+  proved on the standard output. In case of script, prints all the non-proved
+  sub-goals of the script.
 \item[\tt -wp-out <dir>] sets the user directory where proof
   obligations are saved. The directory is created if it does not exist
   yet. Its content is not cleaned up automatically.
@@ -1593,15 +1626,13 @@ The main option to control cache usage is \verb+-wp-cache+, documented below:
 \begin{description}
 \item[\tt -wp-cache <mode>] selects the cache mode to use with \textsf{Why-3}
   provers. The default mode is \verb'update' if there is \textsf{WP} session
-  available, and \verb+none+ otherwise.  You can also use the environment
-  variable \texttt{FRAMAC\_WP\_CACHE} instead.
+  available, and \verb+none+ otherwise.
 \item[\tt -wp-cache-dir <dir>] select the directory where cached results are
   stored. By default, the cache is store in the \textsf{WP} session
   directory, when available.
-  You can also use the environment variable
-  \texttt{FRAMAC\_WP\_CACHEDIR} instead.
-\item[\tt -wp-cache-env] gives environment variables the precedence over command line options.
-  By default, the command line options take precedence, as usual.
+\item[\tt -wp-cache-env] makes environment variables
+  \verb|FRAMAC_WP_CACHE|, \verb|FRAMAC_WP_CACHEDIR| and \verb|FRAMAC_WP_SCRIPT|
+  override command line options \verb|-wp-cache|, \verb|-wp-cachedir| and \verb|-wp-script|, respectively.
 \end{description}
 
 The available cache modes are described below:
@@ -1616,16 +1647,7 @@ The available cache modes are described below:
 
 When using cache with a non-\verb+offline+ mode, time and steps limits recorded in the cache are compared to the command line settings to produce meaningful and consistent results. Hence, if you provide more time or more steps from the command line than before, the prover would be run again. If you provide less or equal limits, the cache entries are reused, but \textsf{WP} still report the cached time and step limits to inform you of your previous attempts. For instance, if you have in the cache a « Valid » entry with time 12.4s and re-run it with a timeout of 5s, you will have a « Timeout » result with time 12.4s printed on the console.
 
-\section{Plug-in Developer Interface}
-\label{wp-api}
-
-A full featured \textsf{OCaml} API is exported with the
-\textsf{WP} plug-in. As documented in the \textsf{Frama-C} user manual, simply add the directive \verb!PLUGIN_DEPENDENCIES+=Wp! to the Makefile of your plug-in.
-
-The high-level API for generating and proving properties is exported
-in module \textsf{Wp.API}. The logical interface, compilers, and memory models are also accessible. See the generated \textsf{HTML} documentation of the platform for details.
-
-\section{Proof Obligation Reports}
+\subsection{Proof Obligation Reports}
 
 The \textsf{WP} plug-in can export statistics on generated proof
 obligations. These statistics are called \textit{WP reports} and are
@@ -1640,17 +1662,395 @@ Reports are generated with the following command-line options:
 \begin{description}
 \item[\tt -wp-report <Rspec$_1$,...,Rspec$_n$>] specifies the list of
   reports to export.
-  Each value \texttt{Rspec$_i$} is a \textit{WP report} specification file
-  (described below).
+  Each value \texttt{Rspec$_i$} is a report template specification file.
+  See Section~\ref{wp-template-reports} for details on their structure.
 \item[\tt -wp-report-basename <name>] set the basename for exported
   reports (described below).
 \item[\tt -wp-report-json <file>.json] output the proof report in JSON format.
+  See Section~\ref{wp-json-reports} for details on the JSON report format.
 \end{description}
 
-See sections below for details on the generated report formats.
+\subsection{Persistent Options}
+\label{wp-persistent}
 
-\clearpage
-\subsection{JSON Reports}
+As a general observation, almost \emph{none} of the internal
+\textsf{WP} data is kept in memory after each execution. Most of the
+generated proof-obligation data is stored on disk before being sent to
+provers, and they are stored in a temporary directory that is removed
+upon \textsf{Frama-C} exit (see also \texttt{-wp-out} option).
+
+The only information which is added to the \textsf{Frama-C} kernel
+consists in a new status for those properties proved by \textsf{WP} plug-in with
+their dependencies.
+
+Thus, when combining \textsf{WP}
+options with \texttt{-then}, \texttt{-save} and \texttt{-load}
+options, the user should be aware of the following precisions:
+\begin{description}
+\item[\tt -wp, -wp-prop, -wp-fct, -wp-bhv.] These options make the
+  \textsf{WP} plug-in generate proof-obligations for the selected
+  properties. The values of these options are never saved and they are
+  cleared by \texttt{-then}. Hence, running \texttt{-wp-prop A}
+  \texttt{-then} \texttt{-wp-fct F} does what you expect:
+  properties tagged by \texttt{A} are proved only once.
+\item[\tt -wp-print, -wp-status, -wp-prover, -wp-gen, -wp-detect.]
+  These options do not
+  generate new proof-obligations, but run other actions on all
+  previously generated ones. For the same reasons, they are not saved
+  and cleared by \texttt{-then}.
+\item[\tt -wp-xxx.] All other options are tunings that can be easily
+  turned on and off or set to the desired value.
+  They are saved and kept across \texttt{-then} commands.
+\end{description}
+
+\section{Proof Strategies}
+\label{wp-proof-strategies}
+
+\emph{Introduced since Frama-C 28.0 (Nickel)}
+
+Proof obligations generated by \textsf{WP} are usually discharged by an
+\textsf{SMT} solver specified by the user through command line option
+\verb$-wp-prover$. As described in previous sections, complex proof obligations
+may also be split into simpler sub-goals by applying \emph{Tactics} from the
+\textsf{TIP} user interface.
+
+Proof strategies provide user-defined heuristics to automatically try various
+combinations of provers, timeouts and tactics, depending on the proof
+context. This is a much more effective technique than relying on manually edited
+scripts through the \textsf{TIP} user interface. Here are some benefits of using
+proof strategies:
+\begin{itemize}
+\item Proof strategies are automatic: there is no need for entering GUI session.
+\item Proof strategies can be associated to individual functions, lemmas or properties,
+  or tried globally.
+\item Tactics are applied following patterns: depending on your case study, you can
+  define fine-tuned strategies to solve your common issues.
+\item Proof strategies are compatible with TIP-based scripts: you can use
+  strategies to complete scripts and conversely.
+\item Scripts are easier to replay and to update: each proof node now records
+  which strategy was involved in the past, so that incomplete or broken proofs
+  can be recovered easily.
+\end{itemize}
+
+Proof Strategies are defined thanks to dedicated ACSL extensions and controlled
+by specific command-line options. Note that those extensions are only available
+when command-line option \verb+-wp-strategy+ is specified.  The syntax of ACSL
+extensions for proof strategies is defined below:
+
+\newcommand{\pdots}{\,,\,\ldots,\,}
+
+\begin{center}
+  \begin{tabular}{l}
+    \verb+@strategy+ \textit{name}\,: \\
+    \quad\quad\textit{alternative}\,, \\
+    \quad\quad\ldots, \\
+    \quad\quad\textit{alternative}\,; \\
+    \\
+    \verb+@proof+ \textit{name}\,: \textit{target}\pdots\textit{target}\,;
+  \end{tabular}
+\end{center}
+
+A \emph{strategy} must be defined by a unique name and consists of a list of
+\emph{alternatives} that will be tried in order until proof completion.
+
+Proof hints can be specified to associate strategies to lemma, function or
+property names. Hints consists of a strategy name to be used for one or many
+proof targets.  Targets follow the same conventions than \verb$-wp-prop$
+command-line option, although quotes might be necessary,
+e.g. \verb$"@requires"$.  A proof hint specification applies for all properties
+matching the property filter.  Many proof hints might apply, in which
+case, proof hints will be tried in order.
+
+Strategies shall be defined \emph{before} being used as proof hints. It is
+recommended to write strategies in separated \verb$*.c$ or \verb$*.i$ files and
+to write proof hints right after their target definition.
+
+Strategy consists of list of alternatives with the following syntax:
+
+\begin{center}
+  \begin{tabular}{l}
+    \textit{alternative} $::=$ \\
+    \quad$|$\quad\verb+\prover+(\verb+"p"+\pdots\verb+"p"+, \textit{timeout}) \\
+    \quad$|$\quad\verb+\tactic+(\verb+"id"+, \textit{param}\pdots\textit{param}) \\
+    \quad$|$\quad\verb+\auto+(\verb+"id"+\pdots\verb+"id"+) \\
+    \quad$|$\quad\verb+\default+ \\
+    \quad$|$\quad\textit{strategy}
+  \end{tabular}
+\end{center}
+
+Each form \emph{alternative} consists of one possible solution to discharge a proof obligation:
+\begin{itemize}
+\item \verb+\provers(p,...,p,time)+ will try the specified provers in sequence
+  with a specified timeout. Provers and/or timeout can be omitted, in such a case the
+  command-line options \verb+-wp-prover+ and \verb+-wp-timeout+ are used instead.
+  Sub-second timeout can also be specified, eg. \verb+0.2+ for 200 milliseconds. Prover
+  names must be individually quoted, with the same syntax as \verb+-wp-prover+
+  command line option.
+\item \verb+\tactic(id,prm...)+ will try to apply the specified tactic with the
+  associated parameters. Tactic parameters allow to select the target of the tactic,
+  and the strategy to be used on generated sub-goals.
+\item \verb+\auto(id,...)+ will try to apply the (deprecated) auto-strategies
+  available in \textsf{WP} versions prior to Cobalt.
+\item \textit{name} or \verb$\default$ tries the specified strategy.
+\end{itemize}
+
+The default strategy consists in applying the strategies specified through the
+command-line option \verb+-wp-strategy s,...+, in order.
+
+Tactic parameters are specified using the following syntax:
+
+\begin{center}
+  \begin{tabular}{l}
+    \textit{param} $::=$ \\
+    \quad$|$\quad\verb+\goal+(\textit{pattern},\ldots) \\
+    \quad$|$\quad\verb+\when+(\textit{pattern},\ldots) \\
+    \quad$|$\quad\verb+\ingoal+(\textit{pattern},\ldots) \\
+    \quad$|$\quad\verb+\incontext+(\textit{pattern},\ldots) \\
+    \quad$|$\quad\verb+\pattern+(\textit{pattern},\ldots) \\
+    \quad$|$\quad\verb+\select+(\textit{pattern}) \\
+    \quad$|$\quad\verb+\param+(\textit{id},\textit{value}) \\
+    \quad$|$\quad\verb+\child+(\textit{id},\textit{strategy}) \\
+    \quad$|$\quad\verb+\children+(\textit{strategy}) \\
+  \end{tabular}
+\end{center}
+
+Tactic parameters are interpreted as follows:
+\begin{itemize}
+\item \verb+\goal(ps)+, \verb+\when(ps)+ and other patterns are used to
+  match parts of the current proof node. The form \verb+\when(ps)+ looks
+  for top-level hypotheses patterns, \verb+\goal(ps)+ for top-level goal patterns.
+  Form \verb+\ingoal(ps)+ and \verb+\incontext(ps)+ respectectively matches patterns
+  deeper inside the goal or the hypotheses, and finally
+  \verb+\pattern(ps)+ searches in the entire proof obligation.
+  When several patterns are given, all must apply and agree on common pattern variables.
+  Pattern syntax is specified below.
+\item \verb+\select(v)+ defines the main target of the selected tactic. The
+  value \verb+v+ uses the same syntax as patterns, with pattern variables
+  replaced with their matched values. Few tactics support multiple selection,
+  in which case, multiple values can be provided.
+  When no selection is specified, the first
+  specified pattern is used as an implicit target. When no selection nor pattern
+  is selected, the default selection is the proof goal.
+\item \verb+\param(p,v)+ configures the parameter value \verb+p+ of the selected
+  tactic with the associated value.
+\item \verb+\child(a,s)+ applies strategy \verb+s+ to prove the sub-goal named
+  \verb+a+ of the tactic.
+\item \verb+\children(s)+ applies strategy \verb+s+ on (other) sub-goals of the
+  tactic. If unspecified, the strategy used for the current node is applied.
+\end{itemize}
+
+Tactics identifiers and their parameters can be obtained from the command line:
+\begin{itemize}
+\item \verb|frama-c -wp-tactic ?| lists all the registered tactic identifiers;
+\item \verb|frama-c -wp-tactic id,...| prints detailed infos for the selected tactics.
+\end{itemize}
+
+Patterns and values are a closed to raw proof obligation formulae, with the
+following restrictions and meaning:
+\begin{itemize}
+\item variables are pattern variables;
+\item pattern \verb+_+ matches any value;
+\item pattern \verb+x:p+ matches pattern \verb+p+ and bind its value to variable \verb+x+;
+\item pattern \verb+a..b+ matches integer constants in the specified (constant) range.
+\item pattern \verb+\any(p,...)+ matches any of the specified patterns.
+\item patterns \verb+p[k]+ and \verb+p[k->v]+ matches array operations, e.g. for memory models;
+\item ACSL operators have their usual meaning;
+\item ACSL list operators \verb+[|...|]+, \verb+^+ and \verb+*^+ are also recognized;
+\item function calls must use their printed name, as they appear in proof nodes;
+\item for function patterns, trailing dots can be used to match any number of
+  arguments, like in \verb+f(x,y,(..))+ for instance.
+\end{itemize}
+
+It is highly recommended using the graphical user interface or \verb+-wp-print+
+to build patterns expression and values.
+
+\section{Structure of JSON Scripts}
+\label{wp-json-scripts}
+
+The proof scripts generated by using the Interactive Proof Editor (Section~\ref{wp-proof-editor})
+are saved in the \textsf{Frama-C/WP} session as \textsf{JSON} files. This section defines
+the format of session scripts precisely.
+
+\textsf{JSON} scripts files are located in the \texttt{<session>/wp/scripts} sub-directory
+of the \textsf{Frama-C} session directory (set with command line option \texttt{-session})
+or in the \texttt{<wpsession>/scripts} sub-directory of the \textsf{Frama-C/WP} session
+directory (set with command line option \texttt{-wp-session}).
+
+The proof scripts for goal named \texttt{<goal>} is stored in a single file \texttt{<goal>.json} ; the
+format of the \texttt{<goal>} name is identical to the one used by the \textsf{Frama-C/Report} plug-in
+for its \textsf{JSON} output.
+
+The content of each script file is an array of alternatives, each alternative being a record with
+two possible structures, that might represent a \textit{prover} attempt or the application of a
+\textit{tactic}:
+
+\begin{align*}
+    \mathit{wp.script} &::= \mathtt{[} \mathit{wp.alternative} , \ldots \mathtt{]} \\
+    \mathit{wp.alternative} &::= \mathit{wp.prover} \;|\; \mathit{wp.tactic}
+\end{align*}
+
+\paragraph{Prover Attempts} The proof script records previous attempts to discharge a proof obligation
+with external provers (also called decision procedures).
+Each attempt is represented by a \textsf{JSON} record with the following fields:
+
+\begin{align*}
+    \mathit{wp.prover} &::=
+    \left\{
+    \begin{array}{rl}
+        \mathtt{"prover"}  :& \mathit{string}, \\
+        \mathtt{"verdict"} :& \mathit{wp.verdict}, \\
+        \mathtt{"time"}    :& \mathit{number}? \\
+        \mathtt{"steps"}   :& \mathit{number}? \\
+        \mathtt{"depth"}   :& \mathit{number}? \\
+    \end{array}
+    \right\} \\
+    \mathit{wp.verdict} &::=
+    \begin{array}[t]{l}
+    \mathtt{"none"} ~|~
+    \mathtt{"valid"} ~|~
+    \mathtt{"unknown"} ~|~ \\
+    \mathtt{"timeout"} ~|~
+    \mathtt{"stepout"} ~|~
+    \mathtt{"invalid"} ~|~
+    \mathtt{"failed"}
+    \end{array}
+\end{align*}
+
+Remark that, since the proof scripts do not record the proof obligation that was exercised, there is no
+guarantee that replaying the script on a (potentially new) proof obligation would issue the same result.
+Hence, prover attempts \emph{must} not be used as a cache, but can serve as a hint for choosing among
+several alternatives.
+
+\paragraph{Proof Tactic} Applying a tactic is represented by a \textsf{JSON} record with the following
+fields:
+
+\begin{align*}
+    \mathit{wp.tactic} &::=
+    \left\{
+    \begin{array}{rl}
+        \mathtt{"tactic"}   :& \mathit{string}, \\
+        \mathtt{"header"}   :& \mathit{string} ? \\
+        \mathtt{"select"}   :& \mathit{wp.selection}, \\
+        \mathtt{"params"}   :& \mathtt{\{}\; \mathit{string}:\mathit{wp.param} ,\ldots \;\mathtt{\}} ? \\
+        \mathtt{"children"} :& \mathtt{\{}\; \mathit{string}:\mathit{wp.script}, \ldots \;\mathtt{\}} ? \\
+        \mathtt{"strategy"} :& \mathit{string} ? \\
+    \end{array}
+    \right\}
+\end{align*}
+
+The \verb"header" field is just a descriptive title and has no special
+meaning. The \verb"tactic" identifies the tactic, as it has been registered in
+the \textsf{Frama-C/WP} internal API.  The \verb"selection" is an opaque
+encoding of the target of the tactic inside the proof obligation structure. The
+\verb"params" array stores the value of tactic parameters, if any.  The
+\verb"children" stores the proof scripts associated with each sub-goal generated
+by applying the specified tactic on a proof obligation. Finally, the
+\verb"strategy" fields is used to recall which user-defined proof strategy was
+used to trigger the tactic (See Section~\ref{wp-proof-strategies}).
+
+\paragraph{Tactic Parameters} Values of tactical parameters are encoded with the
+following \textsf{JSON} format, depending on the internal type of the parameter
+value:
+
+\begin{align*}
+    \mathit{wp.param} ::=\;&
+    \mathit{bool} ~|~ \mathit{number} ~|~ \mathit{string} \\
+    |\;&\mathit{wp.named} ~|~ \mathit{wp.selection} \\
+    \mathit{wp.named} ::= &\mathtt{null} ~|~
+    \left\{
+    \begin{array}{rl}
+        \mathtt{"id"} :& \mathit{string}, \\
+        \mathtt{"title"} :& \mathit{string}? \\
+        \mathtt{"description"} :& \mathit{string}?
+    \end{array}
+    \right\}
+\end{align*}
+
+Named items (\textit{wp.named}) corresponds, for instance, to searched lemmas.
+Selections corresponds to terms or expressions selected by the user \emph{via}
+the graphical user interface, like the target of the tactic, as described below.
+
+\paragraph{Tactic Selection} The target of the tactic
+is identified by a complex structure
+encoding on which part of the proof obligation it shall be applied. Since the
+exact structure of the proof obligation may vary from time to time, this structure
+allows for searching in the proof obligation a \emph{pattern} that ressemble the
+original target that was originally selected by the user during an interactive
+session with the \textsf{Frama-C/WP} graphical user interface.
+
+Such \emph{patterns} are encoded as follows:
+
+\newcommand{\dash}{\rule[0.5ex]{1ex}{1pt}}
+
+\begin{align*}
+    \mathit{wp.selection}
+    ::=\;& \mathtt{null} \\
+    |\;\;& \mathtt{\{}\; \mathtt{"select":"clause\dash{}goal"},\;
+                         \mathit{wp.pattern} \;\mathtt{\}} \\
+    |\;\;& \mathtt{\{}\; \mathtt{"select":"inside\dash{}goal"},\;
+                         \mathit{wp.occur},\; \mathit{wp.pattern} \;\mathtt{\}} \\
+    |\;\;& \mathtt{\{}\; \mathtt{"select":"clause\dash{}step"},\;
+                         \mathit{wp.at},\; \mathit{wp.kind},\;
+                         \mathit{wp.pattern} \;\mathtt{\}} \\
+    |\;\;& \mathtt{\{}\; \mathtt{"select":"inside\dash{}step"},\;
+                         \mathit{wp.at},\; \mathit{wp.kind},\;
+                         \mathit{wp.occur},\; \mathit{wp.pattern} \;\mathtt{\}} \\
+    |\;\;& \mathtt{\{}\; \mathtt{"select":"range"},\;
+                         \mathtt{"min"}:\mathit{number},\;
+                         \mathtt{"max"}:\mathit{number} \;\mathtt{\}} \\
+    |\;\;& \mathtt{\{}\; \mathtt{"select":"kint"},\;
+                         \mathtt{"val"}:\mathit{number} \;\mathtt{\}} \\
+    |\;\;& \mathtt{\{}\; \mathtt{"select":"compose"},\;
+                         \mathtt{"id"}:\mathit{string},\;
+                         \mathtt{"args"}:[\mathit{wp.selection},\ldots]
+                         \;\mathtt{\}} \\
+% --
+    \mathit{wp.pattern} ::=\;& \mathtt{"pattern"} : \mathit{string} \\
+    \mathit{wp.occur}   ::=\;& \mathtt{"occur"} : \mathit{number} \\
+    \mathit{wp.at}      ::=\;& \mathtt{"at"} : \mathit{number} \\
+    \mathit{wp.kind}    ::=\;& \mathtt{"kind"} : \mathtt{"have"|"type"|"init"|"branch"|"either"|"state"} \\
+\end{align*}
+
+The various components of selection patterns have the following meaning: \textit{wp.pattern} encodes
+a term or predicate pattern; \textit{wp.occur} designates which occurrence of the pattern to select,
+in case of there is many of them inside the selected goal or hypothesis; \textit{wp.at} designates the
+order of the selected hypothesis inside the proof obligation (the pattern is searched around this value),
+and \textit{wp.kind} its kind.
+
+The \textit{wp.pattern} is a simple string that encodes the head of the structure of the
+selected term or formulæ inside the designated goal or hypothesis. It is the concatenation of
+the first 32 head nodes of width-first traversal of the selected term, each node being represented by
+the following string:
+\begin{itemize}
+    \item constant are represented by their value,
+    \item free variables by their base-name prefixed with \verb'$',
+    \item bound variables by their de-Bruijn index prefixed with \verb'#',
+    \item true and false by \verb"T" and \verb"F", and quantifiers by \verb"\F" and \verb"\E",
+    \item operators by \verb"&,|,!,~,+,-,*,/,%<,>,=,>=,/,?"
+    \item array operations by \verb"[]", \verb"[.]" and \verb"[=]"
+    \item record operations by \verb".fd" and \verb"{fd,...}"
+    \item function calls by their name
+\end{itemize}
+
+For instance, the term $(x_1 \leq x_2+1)$ will be represented by the pattern \verb|"<=$x+$x1"|.
+
+\paragraph{Script Priority} When several alternatives are available for
+discharging a proof obligation, the \texttt{script} and \texttt{tip} provers
+of \textsf{Frama-C/WP} choose which one to apply first according to the
+following heuristic:
+\begin{enumerate}
+    \item try internal prover \texttt{"Qed"} with a \texttt{"valid"} verdict;
+    \item try any SMT prover with a \texttt{"valid"} verdict;
+    \item try the \texttt{"Coq"} proof assistant with a \texttt{"valid"} verdict;
+    \item try any Tactic alternative;
+    \item finally try the remaining Prover alternatives.
+\end{enumerate}
+
+Inside the same level of priority, alternatives are kept in their original
+order.
+
+\section{Structure of JSON Reports}
+\label{wp-json-reports}
 
 The generated JSON report format consists of an array of JSON records, one for
 each generated toplevel goal. Each record consists of the following fields,
@@ -1700,7 +2100,8 @@ some of them being optional when indicated:
 Notice that the JSON report file is printed in compact form without extra space nor indentation,
 unless verbose level is greater than 2 or debug level is greater than 1.
 
-\subsection{Template-based Reports}
+\section{Structure of Report Templates}
+\label{wp-template-reports}
 
 Reports are created from user defined wp-report specification files.
 The general format of a wp-report file is as follows:
@@ -1836,39 +2237,6 @@ current names:
 \end{center}
 \clearpage
 
-%-----------------------------------------------------------------------------
-\section{Plug-in Persistent Data}
-\label{wp-persistent}
-
-As a general observation, almost \emph{none} of the internal
-\textsf{WP} data is kept in memory after each execution. Most of the
-generated proof-obligation data is stored on disk before being sent to
-provers, and they are stored in a temporary directory that is removed
-upon \textsf{Frama-C} exit (see also \texttt{-wp-out} option).
-
-The only information which is added to the \textsf{Frama-C} kernel
-consists in a new status for those properties proved by \textsf{WP} plug-in with
-their dependencies.
-
-Thus, when combining \textsf{WP}
-options with \texttt{-then}, \texttt{-save} and \texttt{-load}
-options, the user should be aware of the following precisions:
-\begin{description}
-\item[\tt -wp, -wp-prop, -wp-fct, -wp-bhv.] These options make the
-  \textsf{WP} plug-in generate proof-obligations for the selected
-  properties. The values of theses options are never saved and they are
-  cleared by \texttt{-then}. Hence, running \texttt{-wp-prop A}
-  \texttt{-then} \texttt{-wp-fct F} does what you expect:
-  properties tagged by \texttt{A} are proved only once.
-\item[\tt -wp-print, -wp-prover, -wp-gen, -wp-detect.] These options do not
-  generate new proof-obligations, but run other actions on all
-  previously generated ones. For the same reasons, they are not saved
-  and cleared by \texttt{-then}.
-\item[\tt -wp-xxx.] All other options are tunings that can be easily
-  turned on and off or set to the desired value.
-  They are saved and kept across \texttt{-then} commands.
-\end{description}
-
 %-----------------------------------------------------------------------------
 
 % vim: spell spelllang=en
diff --git a/src/plugins/wp/doc/manual/wp_simplifier.tex b/src/plugins/wp/doc/manual/wp_simplifier.tex
index 2e3e82551aa4e94a1ab36ac54e667b9e3ff97d0c..83548a9f1a0d19e5e58999c020fa87d94d075d87 100644
--- a/src/plugins/wp/doc/manual/wp_simplifier.tex
+++ b/src/plugins/wp/doc/manual/wp_simplifier.tex
@@ -73,7 +73,7 @@ Adding a new fact $H$ to $\Gamma$ is denoted by $\Gamma\oplus H$ ;
 rewriting a term of predicate $e$ into $e'$ with respect to $\Gamma$
 is denoted by $\Gamma\models e\triangleright e'$.
 
-\paragraph{Inference Law.} 
+\paragraph{Inference Law.}
 A hypothesis is simplified and added to the knowledge base to
 simplify the goal.
 \[\LAW%
@@ -164,183 +164,3 @@ conditional is:
 This form actually factorizes the common postcondition to $A$ and $B$,
 which makes the \emph{weakest precondition} calculus linear in the
 number of program statements.
-
-\section{Structure of JSON Scripts}
-
-The proof scripts generated by using the Interactive Proof Editor (Section~\ref{wp-proof-editor})
-are saved in the \textsf{Frama-C/WP} session as \textsf{JSON} files. This section defines
-the format of session scripts precisely.
-
-\textsf{JSON} scripts files are located in the \texttt{<session>/wp/scripts} sub-directory
-of the \textsf{Frama-C} session directory (set with command line option \texttt{-session})
-or in the \texttt{<wpsession>/scripts} sub-directory of the \textsf{Frama-C/WP} session
-directory (set with command line option \texttt{-wp-session}).
-
-The proof scripts for goal named \texttt{<goal>} is stored in a single file \texttt{<goal>.json} ; the
-format of the \texttt{<goal>} name is identical to the one used by the \textsf{Frama-C/Report} plug-in
-for its \textsf{JSON} output.
-
-The content of each script file is an array ofs alternatives, each alternative being a record with
-two possible structures, that might represent a \textit{prover} attempt or the application of a
-\textit{tactic}:
-
-\begin{align*}
-    \mathit{wp.script} &::= \mathtt{[} \mathit{wp.alternative} , \ldots \mathtt{]} \\
-    \mathit{wp.alternative} &::= \mathit{wp.prover} \;|\; \mathit{wp.tactic}
-\end{align*}
-
-\paragraph{Prover Attempts} The proof script records previous attempts to discharge a proof obligation
-with external provers (also called decision procedures).
-Each attempt is represented by a \textsf{JSON} record with the following fields:
-
-\begin{align*}
-    \mathit{wp.prover} &::=
-    \left\{
-    \begin{array}{rl}
-        \mathtt{"prover"}  :& \mathit{string}, \\
-        \mathtt{"verdict"} :& \mathit{wp.verdict}, \\ 
-        \mathtt{"time"}    :& \mathit{number}? \\ 
-        \mathtt{"steps"}   :& \mathit{number}? \\ 
-        \mathtt{"depth"}   :& \mathit{number}? \\ 
-    \end{array}
-    \right\} \\
-    \mathit{wp.verdict} &::=
-    \begin{array}[t]{l}
-    \mathtt{"none"} ~|~ 
-    \mathtt{"valid"} ~|~ 
-    \mathtt{"unknown"} ~|~ \\
-    \mathtt{"timeout"} ~|~ 
-    \mathtt{"stepout"} ~|~ 
-    \mathtt{"invalid"} ~|~
-    \mathtt{"failed"}
-    \end{array}
-\end{align*}
-
-Remark that, since the proof scripts do not record the proof obligation that was exercised, there is no
-guarantee that replying the script on a (potentially new) proof obligation would issue the same result.
-Hence, prover attempts \emph{must} not be used as a cache, but can serve as a hint for choosing among
-several alternatives.
-
-\paragraph{Proof Tactic} Applying a tactic is represented by a \textsf{JSON} record with the following
-fields:
-
-\begin{align*}
-    \mathit{wp.tactic} &::=
-    \left\{
-    \begin{array}{rl}
-        \mathtt{"tactic"}   :& \mathit{string}, \\
-        \mathtt{"header"}   :& \mathit{string} ? \\ 
-        \mathtt{"select"}   :& \mathit{wp.selection}, \\ 
-        \mathtt{"params"}   :& \mathtt{\{}\; \mathit{string}:\mathit{wp.param} ,\ldots \;\mathtt{\}} ? \\ 
-        \mathtt{"children"} :& \mathtt{\{}\; \mathit{string}:\mathit{wp.script}, \ldots \;\mathtt{\}} ? \\ 
-    \end{array}
-    \right\}
-\end{align*}
-
-The \verb"header" field is just a descriptive title and has no special meaning. The \verb"tactic"
-identifies the tactic, as it has been registered in the \textsf{Frama-C/WP} internal API.
-The \verb"selection" is an opaque encoding of the target of the tactic inside the proof obligation
-structure. The \verb"params" array stores the value of tactic parameters, if any.
-The \verb"children" stores the proof scripts associated with each sub-goal generated by applying
-the specified tactic on a proof obligation.
-
-\paragraph{Tactic Parameters} Values of tactical parameters are encoded with the
-following \textsf{JSON} format, depending on the internal type of the parameter 
-value:
-
-\begin{align*}
-    \mathit{wp.param} ::=\;&
-    \mathit{bool} ~|~ \mathit{number} ~|~ \mathit{string} \\
-    |\;&\mathit{wp.named} ~|~ \mathit{wp.selection} \\
-    \mathit{wp.named} ::= &\mathtt{null} ~|~
-    \left\{
-    \begin{array}{rl}
-        \mathtt{"id"} :& \mathit{string}, \\
-        \mathtt{"title"} :& \mathit{string}? \\
-        \mathtt{"description"} :& \mathit{string}?
-    \end{array}
-    \right\}
-\end{align*}
-
-Named items (\textit{wp.named}) corresponds, for instance, to searched lemmas.
-Selections corresponds to terms or expressions selected by the user \emph{via}
-the graphical user interface, like the target of the tactic, as described below.
-
-\paragraph{Tactic Selection} The target of the tactic
-is identified by a complex structure
-encoding on which part of the proof obligation it shall be applied. Since the
-exact structure of the proof obligation may vary from time to time, this structure
-allows for searching in the proof obligation a \emph{pattern} that ressemble the
-original target that was originally selected by the user during an interactive
-session with the \textsf{Frama-C/WP} graphical user interface.
-
-Such \emph{patterns} are encoded as follows:
-
-\newcommand{\dash}{\rule[0.5ex]{1ex}{1pt}}
-
-\begin{align*}
-    \mathit{wp.selection}
-    ::=\;& \mathtt{null} \\
-    |\;\;& \mathtt{\{}\; \mathtt{"select":"clause\dash{}goal"},\;
-                         \mathit{wp.pattern} \;\mathtt{\}} \\
-    |\;\;& \mathtt{\{}\; \mathtt{"select":"inside\dash{}goal"},\;
-                         \mathit{wp.occur},\; \mathit{wp.pattern} \;\mathtt{\}} \\
-    |\;\;& \mathtt{\{}\; \mathtt{"select":"clause\dash{}step"},\;
-                         \mathit{wp.at},\; \mathit{wp.kind},\;
-                         \mathit{wp.pattern} \;\mathtt{\}} \\
-    |\;\;& \mathtt{\{}\; \mathtt{"select":"inside\dash{}step"},\;
-                         \mathit{wp.at},\; \mathit{wp.kind},\;
-                         \mathit{wp.occur},\; \mathit{wp.pattern} \;\mathtt{\}} \\
-    |\;\;& \mathtt{\{}\; \mathtt{"select":"range"},\;
-                         \mathtt{"min"}:\mathit{number},\;
-                         \mathtt{"max"}:\mathit{number} \;\mathtt{\}} \\                         
-    |\;\;& \mathtt{\{}\; \mathtt{"select":"kint"},\;
-                         \mathtt{"val"}:\mathit{number} \;\mathtt{\}} \\
-    |\;\;& \mathtt{\{}\; \mathtt{"select":"compose"},\;
-                         \mathtt{"id"}:\mathit{string},\;
-                         \mathtt{"args"}:[\mathit{wp.selection},\ldots]
-                         \;\mathtt{\}} \\
-% --
-    \mathit{wp.pattern} ::=\;& \mathtt{"pattern"} : \mathit{string} \\
-    \mathit{wp.occur}   ::=\;& \mathtt{"occur"} : \mathit{number} \\
-    \mathit{wp.at}      ::=\;& \mathtt{"at"} : \mathit{number} \\
-    \mathit{wp.kind}    ::=\;& \mathtt{"kind"} : \mathtt{"have"|"type"|"init"|"branch"|"either"|"state"} \\
-\end{align*}
-
-The various components of selection patterns have the following meaning: \textit{wp.pattern} encodes
-a term or predicate pattern; \textit{wp.occur} designates which occurrence of the pattern to select,
-in case of there is many of them inside the selected goal or hypothesis; \textit{wp.at} designates the
-order of the selected hypothesis inside the proof obligation (the pattern is searched around this value),
-and \textit{wp.kind} its kind.
-
-The \textit{wp.pattern} is an simple string that encodes the head of the structure of the 
-selected term or formulæ inside the designated goal or hypothesis. It is the concatenation of
-the first 32 head nodes of width-first traversal of the selected term, each node being represented by
-the following string:
-\begin{itemize}
-    \item constant are represented by their value,
-    \item free variables by their base-name prefixed with \verb'$',
-    \item bound variables by their de-Bruijn index prefixed with \verb'#',
-    \item true and false by \verb"T" and \verb"F", and quantifiers by \verb"\F" and \verb"\E",
-    \item operators by \verb"&,|,!,~,+,-,*,/,%<,>,=,>=,/,?"
-    \item array operations by \verb"[]", \verb"[.]" and \verb"[=]"
-    \item record operations by \verb".fd" and \verb"{fd,...}"
-    \item function calls by their name
-\end{itemize}
-
-For instance, the term $(x_1 \leq x_2+1)$ will be represented by the pattern \verb|"<=$x+$x1"|.
-
-\paragraph{Alternative Ordering} When several alternatives are available for
-discharging a proof obligation, the \texttt{script} and \texttt{tip} provers
-of \textsf{Frama-C/WP} choose which one to apply first according to the
-following heuristic:
-\begin{enumerate}
-    \item try internal prover \texttt{"Qed"} with a \texttt{"valid"} verdict;
-    \item try any SMT prover with a \texttt{"valid"} verdict;
-    \item try the \texttt{"Coq"} proof assistant with a \texttt{"valid"} verdict;
-    \item try any Tactic alternative;
-    \item finally try the remaining Prover alternatives.
-\end{enumerate}
-
-Inside the same level of priority, alternatives are kept in their original
-order.
diff --git a/src/plugins/wp/gui/GuiGoal.ml b/src/plugins/wp/gui/GuiGoal.ml
index a5571312675d6543c5885461963918e77ce24ea0..d16760abc2e6427d6fe042034b0ceb232dcf9d8c 100644
--- a/src/plugins/wp/gui/GuiGoal.ml
+++ b/src/plugins/wp/gui/GuiGoal.ml
@@ -117,6 +117,7 @@ class pane (gprovers : GuiConfig.provers) =
   let autofocus = new autofocus in
   let iformat = new iformat in
   let rformat = new rformat in
+  let autosearch = new GuiTactic.autosearch () in
   let strategies = new GuiTactic.strategies () in
   object(self)
 
@@ -145,8 +146,10 @@ class pane (gprovers : GuiConfig.provers) =
             (Why3.Whyconf.Sprover.elements gprovers#get) in
         provers <- why3_provers ;
         List.iter (fun p -> palette#add_tool p#tool) provers ;
+        palette#add_tool autosearch#tool ;
         palette#add_tool strategies#tool ;
-        Strategy.iter strategies#register ;
+        Strategy.iter autosearch#register ;
+        ProofStrategy.iter strategies#register ;
         Tactical.iter
           (fun tac ->
              let gtac = new GuiTactic.tactic tac printer#pp_selection in
@@ -380,23 +383,29 @@ class pane (gprovers : GuiConfig.provers) =
     method private update_tactics = function
       | None ->
         printer#set_target Tactical.Empty ;
+        autosearch#connect None ;
         strategies#connect None ;
         List.iter (fun tactic -> tactic#clear) tactics
       | Some(tree,sequent,sel) ->
         on_proof_context tree
           begin fun () ->
-            strategies#connect (Some (self#strategies sequent)) ;
-            let select (tactic : GuiTactic.tactic) =
-              let process = self#apply in
-              let composer = self#compose in
-              let browser = self#browse in
-              tactic#select ~process ~composer ~browser ~tree sel
-            in
-            List.iter select tactics ;
-            let tgt =
-              if List.exists (fun tactics -> tactics#targeted) tactics
-              then sel else Tactical.Empty in
-            printer#set_target tgt
+            (* configure strategies *)
+            let node = ProofEngine.head tree in
+            let wpo = ProofEngine.head_goal tree in
+            let hints = ProofStrategy.hints ?node wpo in
+            autosearch#connect (Some (self#autosearch sequent));
+            strategies#connect ~hints (Some self#strategies);
+            (* configure tactics *)
+            List.iter (fun (tactic : GuiTactic.tactic) ->
+                let process = self#apply in
+                let composer = self#compose in
+                let browser = self#browse in
+                tactic#select ~process ~composer ~browser ~tree sel
+              ) tactics ;
+            (* target selection feedback *)
+            printer#set_target
+              (if List.exists (fun tactics -> tactics#targeted) tactics
+               then sel else Tactical.Empty)
           end ()
 
     method private update_scriptbar =
@@ -508,9 +517,8 @@ class pane (gprovers : GuiConfig.provers) =
         self#update_provers None ;
         self#update_tactics None ;
       | Proof proof ->
-        let wpo = ProofEngine.head proof in
         begin
-          self#update_provers (Some wpo) ;
+          self#update_provers (Some (ProofEngine.head_goal proof)) ;
           let sequent = printer#sequent in
           let select = printer#selection in
           self#update_tactics (Some(proof,sequent,select)) ;
@@ -553,7 +561,7 @@ class pane (gprovers : GuiConfig.provers) =
             text#hrule ;
             scripter#tree proof ;
             text#hrule ;
-            text#printf "%a@." printer#pp_goal (ProofEngine.head proof) ;
+            text#printf "%a@." printer#pp_goal (ProofEngine.head_goal proof) ;
             text#printf "@{<bf>Goal id:@}  %s@." main.po_gid ;
             text#printf "@{<bf>Short id:@} %s@." main.po_sid ;
             text#hrule ;
@@ -569,7 +577,7 @@ class pane (gprovers : GuiConfig.provers) =
               self#update in
             text#printf "%t@." (composer#print cc ~quit) ;
             text#hrule ;
-            text#printf "%a@." printer#pp_goal (ProofEngine.head proof) ;
+            text#printf "%a@." printer#pp_goal (ProofEngine.head_goal proof) ;
           end ()
       | Browser(proof,cc,tgt) ->
         on_proof_context proof
@@ -581,7 +589,7 @@ class pane (gprovers : GuiConfig.provers) =
               self#update in
             text#printf "%t@." (browser#print cc ~quit) ;
             text#hrule ;
-            text#printf "%a@." printer#pp_goal (ProofEngine.head proof) ;
+            text#printf "%a@." printer#pp_goal (ProofEngine.head_goal proof) ;
           end ()
       | Forking _ -> ()
 
@@ -648,20 +656,19 @@ class pane (gprovers : GuiConfig.provers) =
       | Proof proof ->
         Wutil.later
           begin fun () ->
-            let title = tactic#title in
             try
-              let tactic = ProofScript.jtactic ~title tactic selection in
+              let tactic = ProofScript.jtactic tactic selection in
               let anchor = ProofEngine.anchor proof () in
               self#fork proof (ProofEngine.fork proof ~anchor tactic process)
             with Exit | Not_found | Invalid_argument _ ->
-              text#printf "Application of tactic '%s' failed." title
+              text#printf "Application of tactic '%s' failed." tactic#title
           end
 
     method private search proof = function
       | None -> text#printf "No tactic found.@\n"
       | Some fork -> self#fork proof fork
 
-    method private strategies sequent ~depth ~width auto =
+    method private autosearch sequent ~depth ~width auto =
       match state with
       | Empty | Forking _ | Composer _ | Browser _ -> ()
       | Proof proof ->
@@ -693,6 +700,30 @@ class pane (gprovers : GuiConfig.provers) =
               end
           end
 
+    method private strategies ~depth strategy =
+      match state with
+      | Empty | Forking _ | Composer _ | Browser _ -> ()
+      | Proof proof ->
+        Wutil.later
+          begin fun () ->
+            ProverScript.explore
+              ~depth ?strategy
+              ~result:
+                (fun wpo prv res ->
+                   text#printf "[%a] %a : %a@."
+                     VCS.pp_prover prv
+                     Wpo.pp_title wpo
+                     VCS.pp_result res)
+              ~success:
+                (fun _ _ ->
+                   ProofEngine.forward proof ;
+                   self#update ;
+                   text#printf "Strategie(s) Explored." )
+              proof (ProofEngine.anchor proof ()) ;
+            let server = ProverTask.server () in
+            Task.launch server
+          end
+
     method private backtrack node =
       match state with
       | Empty | Forking _ | Composer _ | Browser _ -> ()
diff --git a/src/plugins/wp/gui/GuiProver.ml b/src/plugins/wp/gui/GuiProver.ml
index 4e32d9956206c0d5fa3211aa9d359c9507a3221f..7f02b9f6fa7f86d59e6cc41cfde465b8d68df89b 100644
--- a/src/plugins/wp/gui/GuiProver.ml
+++ b/src/plugins/wp/gui/GuiProver.ml
@@ -89,7 +89,7 @@ class prover ~(console:Wtext.text) ~prover =
         let spinner = function None -> None | Some s -> Some s#get in
         let config = {
           VCS.valid = false ;
-          VCS.timeout = spinner timeout ;
+          VCS.timeout = Option.map float @@ spinner timeout ;
           VCS.stepout = spinner stepout ;
         } in
         let result wpo _prv _res = self#update wpo in
diff --git a/src/plugins/wp/gui/GuiTactic.ml b/src/plugins/wp/gui/GuiTactic.ml
index ddfe30c345fbece00e09028f186f990658649ba2..079a0c6b3bf9f27865801e5fad218c0e6cd321f6 100644
--- a/src/plugins/wp/gui/GuiTactic.ml
+++ b/src/plugins/wp/gui/GuiTactic.ml
@@ -496,7 +496,7 @@ type hform = {
   widget : Widget.checkbox ;
 }
 
-let compare f g = String.compare f.search#title g.search#title
+let hcompare f g = String.compare f.search#title g.search#title
 
 let spinner ~(form:Wpane.form) ~default ~label ~tooltip =
   let config = "wp.strategies." ^ label in
@@ -506,9 +506,18 @@ let spinner ~(form:Wpane.form) ~default ~label ~tooltip =
   form#add_field ~label spinner#coerce ;
   spinner
 
-type callback = depth:int -> width:int -> Strategy.heuristic list -> unit
+let checkbox ~(form:Wpane.form) ~default ~label ~tooltip =
+  let config = "wp.strategies." ^ label in
+  let value = User.find_bool ~default config in
+  let checkbox = new Widget.checkbox ~label ~tooltip () in
+  checkbox#set value ;
+  checkbox#connect (User.set_bool config) ;
+  form#add_field ~label checkbox#coerce ;
+  checkbox
 
-class strategies () =
+type auto_callback = depth:int -> width:int -> Strategy.heuristic list -> unit
+
+class autosearch () =
   let form = new Wpane.form () in
   let depth = spinner ~form ~default:1 ~label:"Depth"
       ~tooltip:"Limit the number of nested strategies" in
@@ -517,10 +526,10 @@ class strategies () =
   object(self)
     inherit Wpalette.tool
         ~content:form#widget
-        ~label:"Strategies"
-        ~tooltip:"Apply Custom Strategies" ()
+        ~label:"Auto"
+        ~tooltip:"Automated proof search (-wp-auto)" ()
     val mutable hforms : hform list = []
-    val mutable demon : callback option = None
+    val mutable demon : auto_callback option = None
 
     method register (search : Strategy.heuristic) =
       begin
@@ -533,7 +542,7 @@ class strategies () =
         widget#on_event self#update ;
         form#add_row widget#coerce ;
         let hform = { search ; widget } in
-        hforms <- List.merge compare [hform] hforms
+        hforms <- List.merge hcompare [hform] hforms
       end
 
     method private update () =
@@ -567,3 +576,90 @@ class strategies () =
   end
 
 (* -------------------------------------------------------------------------- *)
+(* --- Proof Strategies                                                   --- *)
+(* -------------------------------------------------------------------------- *)
+
+type callback = (depth:int -> ProofStrategy.strategy option -> unit)
+
+type strategy = {
+  strategy : ProofStrategy.strategy ;
+  button : Widget.button ;
+}
+
+class strategies () =
+  let form = new Wpane.form () in
+  let depth = spinner ~form ~default:1 ~label:"Auto depth"
+      ~tooltip:"Depth of exploration" in
+  let hints = checkbox ~form ~default:true ~label:"Hints only"
+      ~tooltip:"Display hints for the current goal" in
+  object(self)
+    inherit Wpalette.tool
+        ~content:form#widget
+        ~label:"Strategies"
+        ~tooltip:"Run the full Proof Strategy Engine (-wp-strategy)" ()
+
+    val mutable registered = false
+    val mutable proofhints : ProofStrategy.strategy list = []
+    val mutable strategies : strategy list = []
+    val mutable callback : callback option = None
+
+    initializer hints#connect (fun _ -> self#update)
+
+    method register (s : ProofStrategy.strategy) =
+      begin
+        registered <- true ;
+        let label = ProofStrategy.name s in
+        let tooltip = Format.asprintf "%a: strategy %s (single step)"
+            Filepath.pp_pos (fst @@ ProofStrategy.loc s) label in
+        let button = new Widget.button ~icon:`MEDIA_PLAY ~label ~tooltip () in
+        button#set_visible false ;
+        button#connect (self#strategy s) ;
+      end
+
+    method connect ?(hints=[]) (cb : callback option) =
+      callback <- cb ;
+      proofhints <- hints ;
+      self#update
+
+    method private strategy (s : ProofStrategy.strategy) () =
+      Option.iter (fun fn -> fn ~depth:depth#get (Some s)) callback
+
+    method private explore () =
+      Option.iter (fun fn -> fn ~depth:depth#get None) callback
+
+    method private setvisible ?(filter=false) ?(rank=0) (s: strategy) =
+      let show = not filter || rank > 0 in
+      s.button#set_visible show ;
+      if show then
+        let name = ProofStrategy.name s.strategy in
+        if rank = 0 then
+          s.button#set_label name
+        else
+          Pretty_utils.ksfprintf s.button#set_label "%s (#%d)" name rank
+
+    method private setrank (s: strategy) =
+      let filter = hints#get in
+      let rec apply (s:strategy) rank = function
+        | [] -> self#setvisible s ~filter
+        | h::hs ->
+          if s.strategy == h then
+            self#setvisible s ~rank
+          else
+            self#setvisible s ~filter ;
+          apply s (succ rank) hs
+      in apply s 1 proofhints
+
+    method private update =
+      if callback = None || not registered then
+        self#set_visible false
+      else
+        begin
+          self#set_visible true ;
+          self#set_status `APPLY ;
+          self#set_action ~callback:self#explore () ;
+          List.iter self#setrank strategies
+        end
+
+  end
+
+(* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/wp/gui/GuiTactic.mli b/src/plugins/wp/gui/GuiTactic.mli
index 868b6445837b6473227671f7996f275e55fba45e..716d4620b65d0e4e0804fa1f2fa6af3ed59893d8 100644
--- a/src/plugins/wp/gui/GuiTactic.mli
+++ b/src/plugins/wp/gui/GuiTactic.mli
@@ -68,11 +68,31 @@ class tactic : Tactical.t -> (Format.formatter -> Tactical.selection -> unit) ->
       selection -> unit
   end
 
-type callback = depth:int -> width:int -> Strategy.heuristic list -> unit
+(* -------------------------------------------------------------------------- *)
+(* --- Auto Dongle                                                        --- *)
+(* -------------------------------------------------------------------------- *)
 
-class strategies : unit ->
+type auto_callback = depth:int -> width:int -> Strategy.heuristic list -> unit
+
+class autosearch : unit ->
   object
     inherit Wpalette.tool
     method register : Strategy.heuristic -> unit
-    method connect : callback option -> unit
+    method connect : auto_callback option -> unit
   end
+
+(* -------------------------------------------------------------------------- *)
+(* --- Strategies Dongle                                                  --- *)
+(* -------------------------------------------------------------------------- *)
+
+type callback = (depth:int -> ProofStrategy.strategy option -> unit)
+
+class strategies : unit ->
+  object
+    inherit Wpalette.tool
+    method register : ProofStrategy.strategy -> unit
+    method connect : ?hints:ProofStrategy.strategy list ->
+      callback option -> unit
+  end
+
+(* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/wp/register.ml b/src/plugins/wp/register.ml
index bd21d8b17014286f93ab87d0ad8ab1ea3509af64..3b5f932999ac3233b3e619b243c2da003ecfe92b 100644
--- a/src/plugins/wp/register.ml
+++ b/src/plugins/wp/register.ml
@@ -62,8 +62,59 @@ let wp_insert_memory_context model =
 (* ---  Printing informations                                           --- *)
 (* ------------------------------------------------------------------------ *)
 
+let do_print_index fmt = function
+  | Wpo.Axiomatic ax -> Wpo.pp_axiomatics fmt ax
+  | Wpo.Function(kf,bhv) -> Wpo.pp_function fmt kf bhv
+
+let rec do_print_parents fmt (node : ProofEngine.node) =
+  Option.iter (do_print_parents fmt) (ProofEngine.parent node) ;
+  Format.fprintf fmt " - %s@\n" (ProofEngine.title node)
+
+let do_print_current fmt tree =
+  match ProofEngine.current tree with
+  | `Main -> ()
+  | `Internal node | `Leaf(_,node) -> do_print_parents fmt node
+
+let do_print_goal_status fmt (g : Wpo.t) =
+  if not (Wpo.is_valid g || Wpo.is_smoke_test g) then
+    begin
+      do_print_index fmt g.po_idx ;
+      Wpo.pp_goal fmt g ;
+      if ProofSession.exists g then
+        Format.fprintf fmt "Script %a@\n" ProofSession.pp_file
+          (ProofSession.filename ~force:false g) ;
+      begin
+        match ProofEngine.get g with
+        | `None | `Script -> ()
+        | `Proof | `Saved ->
+          let tree = ProofEngine.proof ~main:g in
+          match ProofEngine.status tree with
+          | `Unproved | `Invalid | `Proved | `Passed ->
+            Wpo.pp_goal fmt g
+          | `Pending n | `StillResist n ->
+            for i = 0 to n-1 do
+              Format.fprintf fmt "%tSubgoal %d/%d:@\n" Wpo.pp_flow (succ i) n ;
+              ProofEngine.goto tree (`Leaf i) ;
+              do_print_current fmt tree ;
+              Wpo.pp_goal fmt @@ ProofEngine.head_goal tree
+            done
+      end ;
+      Wpo.pp_flow fmt ;
+    end
+
+let do_wp_print_status () =
+  begin
+    Log.print_on_output
+      (fun fmt ->
+         Wpo.iter
+           ~on_goal:(do_print_goal_status fmt) ()) ;
+  end
+
 let do_wp_print () =
   (* Printing *)
+  if Wp_parameters.Status.get () then
+    do_wp_print_status ()
+  else
   if Wp_parameters.Print.get () then
     try
       Wpo.iter ~on_goal:(fun _ -> raise Exit) () ;
@@ -77,6 +128,9 @@ let do_wp_print () =
              ~on_goal:(Wpo.pp_goal_flow fmt) ())
 
 let do_wp_print_for goals =
+  if Wp_parameters.Status.get () then
+    do_wp_print_status ()
+  else
   if Wp_parameters.Print.get () then
     if Bag.is_empty goals
     then Wp_parameters.result "No proof obligations"
@@ -426,9 +480,11 @@ let do_list_scheduled_result () =
 (* ------------------------------------------------------------------------ *)
 
 type script = {
-  mutable tactical : bool ;
+  mutable proverscript : bool ;
+  mutable strategies : bool ;
+  mutable scratch : bool ;
   mutable update : bool ;
-  mutable on_stdout : bool ;
+  mutable stdout : bool ;
   mutable depth : int ;
   mutable width : int ;
   mutable backtrack : int ;
@@ -437,7 +493,7 @@ type script = {
 }
 
 let spawn_wp_proofs ~script goals =
-  if script.tactical || script.provers<>[] then
+  if script.proverscript || script.provers<>[] then
     begin
       let server = ProverTask.server () in
       ignore (Wp_parameters.Share.get_dir "."); (* To prevent further errors *)
@@ -445,12 +501,18 @@ let spawn_wp_proofs ~script goals =
       let cache = Cache.get_mode () in
       Bag.iter
         (fun goal ->
-           if  script.tactical
+           if  script.proverscript
             && not (Wpo.is_trivial goal)
-            && (script.auto <> [] || ProofSession.exists goal)
+            && (script.auto <> [] ||
+                script.strategies ||
+                ProofSession.exists goal ||
+                Wp_parameters.DefaultStrategies.get () <> [] ||
+                ProofStrategy.hints goal <> [])
            then
              ProverScript.spawn
                ~failed:false
+               ~scratch:script.scratch
+               ~strategies:script.strategies
                ~auto:script.auto
                ~depth:script.depth
                ~width:script.width
@@ -475,11 +537,8 @@ let spawn_wp_proofs ~script goals =
     end
 
 let get_prover_names () =
-  match Wp_parameters.Provers.get () with [] -> [ "alt-ergo" ] | pnames -> pnames
-
-let env_script_update () =
-  try Sys.getenv "FRAMAC_WP_SCRIPT" = "update"
-  with Not_found -> false
+  match Wp_parameters.Provers.get () with
+  | [] -> [ "alt-ergo" ] | pnames -> pnames
 
 let compute_provers ~mode ~script =
   script.provers <- List.fold_right
@@ -487,9 +546,8 @@ let compute_provers ~mode ~script =
         match VCS.parse_prover pname with
         | None -> prvs
         | Some VCS.Tactical ->
-          script.tactical <- true ;
-          if pname = "tip" || env_script_update () then
-            script.update <- true ;
+          script.proverscript <- true ;
+          if pname = "tip" then script.strategies <- true ;
           prvs
         | Some prover ->
           let pmode = if VCS.is_auto prover then VCS.Batch else mode in
@@ -508,8 +566,13 @@ let dump_strategies =
                )))
 
 let default_script_mode () = {
-  tactical = false ; update=false ; on_stdout = false ; provers = [] ;
-  depth=0 ; width = 0 ; auto=[] ; backtrack = 0 ;
+  provers = [] ;
+  proverscript = false ;
+  strategies = false ;
+  update = ProofSession.saving_mode () ;
+  scratch = ProofSession.scratch_mode () ;
+  stdout = Wp_parameters.ScriptOnStdout.get ();
+  depth=0 ; width = 0 ; backtrack = 0 ; auto=[] ;
 }
 
 let compute_auto ~script =
@@ -534,7 +597,7 @@ let compute_auto ~script =
                  "Strategy -wp-auto '%s' unknown (ignored)." id
         ) auto ;
       script.auto <- List.rev script.auto ;
-      if script.auto <> [] then script.tactical <- true ;
+      if script.auto <> [] then script.proverscript <- true ;
     end
 
 type session_scripts = {
@@ -572,17 +635,15 @@ let do_collect_session goals =
               | ProofScript.Prover(p,r) -> VCS.is_auto p && VCS.is_valid r
               | ProofScript.Tactic(n,_,_) -> n=0
               | ProofScript.Error _ -> false in
-            let strategy = List.filter keep scripts in
-            if strategy <> [] then
+            let winning = List.filter keep scripts in
+            let file = file goal in
+            if winning <> [] then
               begin
-                let file = file goal in
-                let json = ProofScript.encode strategy in
+                let json = ProofScript.encode winning in
                 updated := (goal, file, json) :: !updated
               end
             else
-            if not (ProofSession.exists goal) then
               begin
-                let file = file goal in
                 let json = ProofScript.encode scripts in
                 incomplete := (goal, file, json) :: !incomplete
               end
@@ -593,7 +654,7 @@ let do_collect_session goals =
     removed = !removed ; }
 
 let do_update_session script session =
-  let stdout = script.on_stdout in
+  let stdout = script.stdout in
   List.iter
     begin fun (g, _, s) ->
       (* we always mark existing scripts *)
@@ -669,17 +730,15 @@ let do_wp_proofs ?provers ?tip (goals : Wpo.t Bag.t) =
   let mode = VCS.parse_mode (Wp_parameters.Interactive.get ()) in
   compute_provers ~mode ~script ;
   compute_auto ~script ;
+  ProofStrategy.typecheck () ;
   begin match provers with None -> () | Some prvs ->
     script.provers <- List.map (fun dp -> VCS.Batch , VCS.Why3 dp) prvs
   end ;
-  begin match tip with None -> () | Some tip ->
-    script.tactical <- tip ;
-    script.update <- tip ;
-  end ;
-  begin
-    script.on_stdout <- Wp_parameters.ScriptOnStdout.get ();
+  begin match tip with None -> () | Some strategies ->
+    script.proverscript <- true ;
+    script.strategies <- strategies ;
   end ;
-  let spawned = script.tactical || script.provers <> [] in
+  let spawned = script.proverscript || script.provers <> [] in
   begin
     if spawned then do_list_scheduled goals ;
     spawn_wp_proofs ~script goals ;
@@ -688,7 +747,9 @@ let do_wp_proofs ?provers ?tip (goals : Wpo.t Bag.t) =
         do_list_scheduled_result () ;
         do_session ~script goals ;
       end
-    else if not (Wp_parameters.Print.get ()) then
+    else
+    if not (Wp_parameters.Print.get () || Wp_parameters.Status.get ())
+    then
       Bag.iter do_wpo_display goals
   end
 
@@ -771,13 +832,9 @@ let pp_wp_parameters fmt =
     if spec <> [] && spec <> ["Typed"] then
       ( let descr = Factory.descr (Factory.parse spec) in
         Format.fprintf fmt " -wp-model '%s'" descr ) ;
-    if not (Wp_parameters.Let.get ()) then Format.pp_print_string fmt
-        " -wp-no-let" ;
-    if Wp_parameters.Let.get () && not (Wp_parameters.Prune.get ())
-    then Format.pp_print_string fmt " -wp-no-prune" ;
-    if Wp_parameters.Split.get () then Format.pp_print_string fmt " -wp-split" ;
+    let dt = Wp_parameters.Timeout.get_default () in
     let tm = Wp_parameters.Timeout.get () in
-    if tm <> 10 then Format.fprintf fmt " -wp-timeout %d" tm ;
+    if tm <> dt then Format.fprintf fmt " -wp-timeout %d" tm ;
     let st = Wp_parameters.Steps.get () in
     if st > 0 then Format.fprintf fmt " -wp-steps %d" st ;
     if not (Kernel.SignedOverflow.get ()) then
@@ -826,6 +883,71 @@ let do_prover_detect () =
              (Why3Provers.ident_wp p)
         ) provers
 
+(* ------------------------------------------------------------------------ *)
+(* --- Tactic Searching                                                 --- *)
+(* ------------------------------------------------------------------------ *)
+
+let pp_field fmt pp (fd : 'a Tactical.field) =
+  let s = Tactical.signature fd in
+  Format.fprintf fmt "@\nParameter %S:" s.vid ;
+  if s.title <> "" then Format.fprintf fmt "@\n  Title: %s" s.title ;
+  if s.descr <> "" then Format.fprintf fmt "@\n  Descr: %s" s.descr ;
+  Format.fprintf fmt "@\n  Default: %a" pp (Tactical.default fd)
+
+let pp_parameter fmt (p : Tactical.parameter) =
+  match p with
+  | Checkbox fd ->
+    pp_field fmt Format.pp_print_bool fd
+  | Spinner(fd,rg) ->
+    pp_field fmt Format.pp_print_int fd ;
+    begin match rg.vmin , rg.vmax with
+      | None,None -> ()
+      | Some a,None -> Format.fprintf fmt "@\n  Range: %d.." a
+      | None,Some b -> Format.fprintf fmt "@\n  Range: ..%d" b
+      | Some a,Some b -> Format.fprintf fmt "@\n  Range: %d..%d" a b
+    end
+  | Composer(fd,_) ->
+    pp_field fmt Tactical.pp_selection fd
+  | Selector(fd,items,eq) ->
+    pp_field fmt
+      (fun fmt v ->
+         List.iter
+           (fun (item : _ Tactical.named) ->
+              if eq v item.value then Format.fprintf fmt "%S" item.vid
+           ) items
+      ) fd ;
+    List.iter
+      (fun (item : _ Tactical.named) ->
+         Format.fprintf fmt "@\n  Value %S: %s" item.vid item.title ;
+         if item.descr <> "" then Format.fprintf fmt " (%s)" item.descr ;
+      ) items
+  | Search(fd,_,_) ->
+    pp_field fmt
+      (fun fmt s ->
+         match s with
+         | None -> Format.pp_print_string fmt "-"
+         | Some v -> Format.fprintf fmt "%S" v.Tactical.title
+      ) fd
+
+let do_search_tactics () =
+  let ts = Wp_parameters.Tactics.get () in
+  if List.mem "?" ts then
+    Wp_parameters.result "@[<hov 2>Registered tactics:%t@]"
+      begin fun fmt ->
+        Tactical.iter (fun t -> Format.fprintf fmt "@ %s" t#id) ;
+      end ;
+  if ts <> [] then
+    Tactical.iter
+      begin fun t ->
+        if List.mem t#id ts then
+          Wp_parameters.result
+            "Tactic %S:@\n\
+             Title: @[<h>%s@]@\n\
+             Descr: @[<h>%s@]%t"
+            t#id t#title t#descr
+            (fun fmt -> List.iter (pp_parameter fmt) t#params)
+      end
+
 (* ------------------------------------------------------------------------ *)
 (* ---  Main Entry Points                                               --- *)
 (* ------------------------------------------------------------------------ *)
@@ -871,6 +993,7 @@ let tracelog () =
 let main = sequence [
     (fun () -> Wp_parameters.debug ~dkey:dkey_main "Start WP plugin...@.") ;
     do_prover_detect ;
+    do_search_tactics ;
     prepare_scripts ;
     cmdline_run ;
     tracelog ;
diff --git a/src/plugins/wp/share/why3/frama_c_wp/vlist.mlw b/src/plugins/wp/share/why3/frama_c_wp/vlist.mlw
index 838aa45061449c66db8dd2d6ec2a567ee2ce883b..90dd0399e3cdf498d95a0e8fc2d56d4f8ae02fcb 100644
--- a/src/plugins/wp/share/why3/frama_c_wp/vlist.mlw
+++ b/src/plugins/wp/share/why3/frama_c_wp/vlist.mlw
@@ -28,61 +28,132 @@ theory Vlist
 
   use int.Int
   use int.ComputerDivision
+  use list.Append
+  use list.HdTl
+  use list.Nth
+  use option.Option
+
+  use export list.List
+  use export list.Length
 
   (* -------------------------------------------------------------------- *)
   (* --- Classical Lists for Alt-Ergo                                 --- *)
   (* -------------------------------------------------------------------- *)
 
-  type list 'a
+  function nil : list 'a = Nil
+
+  function cons (x: 'a) (xs: list 'a) : list 'a = Cons x xs
+
+  let function head (l: list 'a) : 'a
+    requires { l <> Nil }
+    ensures  { hd l = Some result }
+  = match l with Nil -> absurd | Cons h _ -> h end
+
+  let function tail (l: list 'a) : list 'a
+    requires { l <> Nil }
+    ensures  { tl l = Some result }
+  = match l with Nil -> absurd | Cons _ t -> t end
 
-  function nil : list 'a
-  function cons 'a (list 'a) : list 'a
-  function concat (list 'a) (list 'a) : list 'a
-  function repeat (list 'a) int : list 'a
-  function length (list 'a) : int
-  function nth (list 'a) int : 'a
+  function concat (xs: list 'a) (ys: list 'a) : list 'a = xs ++ ys
 
   function elt (x:'a) : list 'a  = cons x nil
 
+  (* repeat *)
+  (* Here we are forced to use axiomatic definition to conform to ACSL *)
+
+  function repeat (xs: list 'a) (n: int) : list 'a
+
+  axiom repeat_empty:
+    forall xs : list 'a.
+      repeat xs 0 = Nil
+
+  axiom repeat_pos:
+    forall xs : list 'a, n. n > 0 ->
+      repeat xs n = xs ++ repeat xs (n - 1)
+
+  (* nth *)
+  (* Here we are forced to use axiomatic definition to conform to ACSL *)
+
+  function nth (l: list 'a) (n: int): 'a
+
+  axiom nth_zero:
+    forall l : list 'a, x.
+      nth (Cons x l) 0 = x
+
+  axiom nth_pos:
+    forall l : list 'a, n.
+      l <> Nil -> 0 < n < length l -> nth l n = nth (tail l) (n-1)
+
+  (* -------------------------------------------------------------------- *)
+  (* --- concat                                                       --- *)
+  (* -------------------------------------------------------------------- *)
+
+  lemma concat_cons: forall u v: list 'a, x: 'a.
+    concat (cons x u) v = cons x (concat u v)
+
+  let lemma head_concat (u v: list 'a)
+    requires { u <> Nil }
+    ensures  { head (concat u v) = head u }
+  = match u with Nil -> absurd | Cons _ _ -> () end
+
+  lemma concat_tail:
+    forall u v: list 'a. u <> Nil -> concat (tail u) v = tail (concat u v)
+
   (* -------------------------------------------------------------------- *)
   (* --- length                                                       --- *)
   (* -------------------------------------------------------------------- *)
 
-  axiom length_pos : forall w:list 'a. (Int.(<=) 0 (length w))
+  lemma length_pos : forall w:list 'a. (Int.(<=) 0 (length w))
+
+  lemma length_nil : length (nil: list 'a) = 0
 
-  axiom length_nil : length (nil: list 'a) = 0
+  lemma length_nil_bis : forall w:list 'a. length w = 0 -> w = nil
 
-  axiom length_nil_bis : forall w:list 'a. length w = 0 -> w = nil
+  lemma length_not_nil : forall w:list 'a. w <> Nil -> 0 < length w
 
-  axiom length_cons :
+  lemma length_cons :
     forall x:'a, w:list 'a [length (cons x w)].
       length (cons x w) = (Int.(+) 1 (length w))
 
-  axiom length_concat :
+  lemma length_tail:
+    forall w: list 'a.
+      w <> Nil -> length (tail w) = length w - 1
+
+  lemma singleton_tail: forall w: list 'a. length w = 1 -> tail w = Nil
+
+  lemma length_concat :
     forall u,v:list 'a [length (concat u v)].
       length (concat u v) = (Int.(+) (length u) (length v))
 
-  axiom length_repeat : 
-    forall w:list 'a, n:int [length (repeat w n)].
-      (Int.(<=) 0 n) -> length (repeat w n) = (Int.( * ) n (length w))
+  let rec lemma length_repeat (w: list 'a) (n: int)
+    requires { 0 <= n }
+    ensures  { length (repeat w n) = (Int.( * ) n (length w)) }
+    variant  { n }
+  = if 0 < n then length_repeat w (n - 1)
 
   (* -------------------------------------------------------------------- *)
   (* --- nth                                                          --- *)
   (* -------------------------------------------------------------------- *)
 
-  axiom nth_cons: 
+  lemma nth_cons:
     forall k:int, x:'a, w:list 'a [nth (cons x w) k].
-      nth (cons x w) k = if k = 0 then x else nth w (k-1)
+      0 <= k <= length w -> nth (cons x w) k = if k = 0 then x else nth w (k-1)
+
+  let lemma nth_head (w: list 'a)
+    requires { w <> Nil }
+    ensures  { nth w 0 = head w }
+  = match w with Nil -> absurd | Cons _ _ -> () end
 
-  axiom nth_concat: 
-    forall u,v:list 'a, k:int [nth (concat u v) k].
-      nth (concat u v) k = if k < length u then nth u k 
-                                           else nth v (Int.(-) k (length u))
+  lemma nth_tail:
+    forall k: int, w: list 'a.
+      0 < k < length w - 1 -> nth (tail w) (k - 1) = nth w k
 
-  axiom nth_repeat: 
-    forall n,k:int, w:list 'a [nth (repeat w n) k].
-      0 <= k < (Int.( * ) n (length w)) -> (Int.(<) 0 (length w)) ->
-      nth (repeat w n) k = nth w (mod k (length w))
+  let rec lemma nth_concat (u v: list 'a) (k: int)
+    requires { 0 <= k < length u + length v }
+    ensures  { nth (concat u v) k =
+                 if k < length u then nth u k else nth v (k - length u) }
+    variant  { k }
+  = if 0 < k && 0 < length u then nth_concat (tail u) v (k - 1)
 
   (* -------------------------------------------------------------------- *)
   (* --- equality of Lists                                            --- *)
@@ -92,8 +163,13 @@ theory Vlist
     length u = length v &&
     forall i:int. 0 <= i < length u -> nth u i = nth v i
 
-  axiom extensionality:
-    forall u,v:list 'a. vlist_eq u v -> u = v
+  let rec lemma extensionality (u v: list 'a)
+    requires { vlist_eq u v }
+    ensures  { u = v }
+    variant  { length u }
+  = assert { forall x: 'a, r: list 'a. head (cons x r) = x } ;
+    assert { forall x: 'a, r: list 'a. tail (cons x r) = r } ;
+    match u, v with Cons _ x, Cons _ y -> extensionality x y | _ -> () end
 
   (* -------------------------------------------------------------------- *)
   (* --- neutral elements                                             --- *)
@@ -101,7 +177,6 @@ theory Vlist
 
   lemma eq_nil_concat:
     forall w:list 'a. vlist_eq (concat nil w) w /\ vlist_eq (concat w nil) w
-  meta "remove_for_" lemma eq_nil_concat
 
   lemma rw_nil_concat_left:
     forall w:list 'a [concat nil w]. concat nil w = w
@@ -114,28 +189,24 @@ theory Vlist
   (* -------------------------------------------------------------------- *)
 
   lemma eq_cons_concat:
-    forall x:'a, v,w:list 'a [concat (cons x v) w]. 
+    forall x:'a, v,w:list 'a [concat (cons x v) w].
       vlist_eq (concat (cons x v) w) (cons x (concat v w))
-  meta "remove_for_" lemma eq_cons_concat
 
   lemma rw_cons_concat:
     forall x:'a, v,w:list 'a [concat (cons x v) w].
       (concat (cons x v) w) = (cons x (concat v w))
-  meta "remove_for_" lemma rw_cons_concat
 
   lemma rw_nil_cons_concat:
     forall x:'a, w:list 'a [concat (cons x nil) w].
       (concat (cons x nil) w) = (cons x w)
-  meta "remove_for_" lemma rw_nil_cons_concat
 
   (* -------------------------------------------------------------------- *)
   (* --- associativity                                                --- *)
   (* -------------------------------------------------------------------- *)
 
-  lemma eq_assoc_concat: 
+  lemma eq_assoc_concat:
     forall u,v,w:list 'a.
       vlist_eq (concat (concat u v) w) (concat u (concat v w))
-  meta "remove_for_" lemma eq_assoc_concat
 
   (* -------------------------------------------------------------------- *)
   (* --- repeat                                                       --- *)
@@ -149,53 +220,76 @@ theory Vlist
     forall w:list 'a [repeat w 0].
       repeat w 0 = nil
 
-  lemma eq_repeat_one:
-    forall w:list 'a. vlist_eq (repeat w 1) w
-  meta "remove_for_" lemma eq_repeat_one
+  let lemma eq_repeat_one (w: list 'a)
+    ensures { vlist_eq (repeat w 1) w }
+  = assert { repeat w 1 = repeat w 0 ++ w }
 
   lemma rw_repeat_one:
     forall w:list 'a [repeat w 1]. repeat w 1 = w
 
+  let rec lemma repeat_more (w: list 'a) (n: int)
+    requires { 0 <= n }
+    ensures  { repeat w (n + 1) = concat (repeat w n) w }
+    variant  { n }
+  = if 0 < n then repeat_more w (n - 1)
+
+  let rec lemma rw_repeat_concat (p q: int) (w: list 'a)
+    requires { 0 <= p }
+    requires { 0 <= q }
+    ensures  { repeat w (Int.(+) p q) = concat (repeat w p) (repeat w q) }
+    variant  { p }
+  = if 0 < p then rw_repeat_concat (p - 1) q w
+
   lemma eq_repeat_concat:
     forall p,q:int, w:list 'a.
       0 <= p -> 0 <= q ->
       vlist_eq (repeat w (Int.(+) p q)) (concat (repeat w p) (repeat w q))
-  meta "remove_for_" lemma eq_repeat_concat
-
-  lemma rw_repeat_concat:
-    forall p,q:int, w:list 'a.
-      0 <= p -> 0 <= q ->
-      repeat w (Int.(+) p q) = concat (repeat w p) (repeat w q)
-  meta "remove_for_" lemma rw_repeat_concat
 
   lemma rw_repeat_after:
     forall p:int, w:list 'a.
        0 <= p -> concat (repeat w p) w = repeat w (Int.(+) p 1)
-  meta "remove_for_" lemma rw_repeat_after
 
   lemma rw_repeat_before:
     forall p:int, w:list 'a.
       0 <= p -> concat w (repeat w p) = repeat w (Int.(+) p 1)
-  meta "remove_for_" lemma rw_repeat_before
+
+  let rec lemma nth_repeat (w: list 'a) (n k: int)
+    requires { 0 <= k < n * length w }
+    ensures  { nth (repeat w n) k = nth w (mod k (length w)) }
+    variant  { n }
+  =
+    if n <= 0 then absurd
+    else if n = 1 then ()
+    else
+      if k < length w
+      then begin
+        assert { (n - 1) * length w >= 1 * length w };
+        nth_repeat w (n - 1) k
+      end
+      else begin
+        let lw = length w in
+          nth_repeat w (n - 1) (k - lw);
+          assert { mod (lw * 1 + (k - lw)) lw = mod (k - lw) lw };
+      end
 
 (*--- To avoid exponential blowup of use of repeat_after by alt-ergo ---*)
 
-function repeat_box (list 'a) int : (list 'a) (* repeat *)
+  function repeat_box (list 'a) int : (list 'a) (* repeat *)
 
-axiom rw_repeat_box_unfold: 
-  forall w:list 'a, n:int [ repeat_box w n ].
-    repeat_box w n = repeat w n
+  axiom rw_repeat_box_unfold:
+    forall w:list 'a, n:int [ repeat_box w n ].
+      repeat_box w n = repeat w n
 
-axiom rw_repeat_plus_box_unfold: 
-  forall w:list 'a, a,b: int [ repeat_box w (Int.(+) a b) ].
-    (Int.(<=) 0 a)
- -> (Int.(<=) 0 b)
- -> repeat_box w (Int.(+) a b) = concat (repeat w a)
+  axiom rw_repeat_plus_box_unfold:
+    forall w:list 'a, a,b: int [ repeat_box w (Int.(+) a b) ].
+      (Int.(<=) 0 a)
+  -> (Int.(<=) 0 b)
+  -> repeat_box w (Int.(+) a b) = concat (repeat w a)
                                                 (repeat w b)
-axiom rw_repeat_plus_one_box_unfold: 
-  forall w:list 'a, n:int [ repeat_box w n ].
-    (Int.(<) 0 n)
- -> (repeat_box w n = (concat (repeat w (Int.(-) n 1)) w)
- && (repeat_box w (Int.(+) n 1) = concat (repeat w n) w))
+  axiom rw_repeat_plus_one_box_unfold:
+    forall w:list 'a, n:int [ repeat_box w n ].
+      (Int.(<) 0 n)
+  -> (repeat_box w n = (concat (repeat w (Int.(-) n 1)) w)
+  && (repeat_box w (Int.(+) n 1) = concat (repeat w n) w))
 
 end
diff --git a/src/plugins/wp/tests/wp_acsl/cnf.i b/src/plugins/wp/tests/wp_acsl/cnf.i
index bffa1773809b5473a14aaab76464a070d5a5f858..b9ba47933cf1f8f70b6e2f5e2ec6531364d5c46b 100644
--- a/src/plugins/wp/tests/wp_acsl/cnf.i
+++ b/src/plugins/wp/tests/wp_acsl/cnf.i
@@ -3,9 +3,9 @@
 */
 
 /* run.config_qualif
-   OPT: -wp -wp-split-depth -2 -wp-par 1 -wp-msg-key cnf -wp-debug 1
+   OPT: -wp -wp-split-cnf -2 -wp-par 1 -wp-msg-key cnf -wp-debug 1
 
-// -wp-split-depth -2 -> replace the Goal by Goal<==>CNF(Goal)
+// -wp-split-cnf -2 debug mode that replaces the Goal by Goal<==>CNF(Goal)
 */
 
 
diff --git a/src/plugins/wp/tests/wp_acsl/label.i b/src/plugins/wp/tests/wp_acsl/label.i
new file mode 100644
index 0000000000000000000000000000000000000000..8e1d2dcfffc7116cadc1eebd04c19237e5afed63
--- /dev/null
+++ b/src/plugins/wp/tests/wp_acsl/label.i
@@ -0,0 +1,29 @@
+/* run.config_qualif
+   DONTRUN:
+*/
+
+int *p;
+
+/*@
+  axiomatic Observer {
+    predicate H{S}(int x) reads *p;
+    predicate P{S}(int x) reads *p;
+    predicate Q{S}(int x) reads *p;
+    predicate W{S}(int x) reads *p;
+  }
+*/
+
+/*@
+  assigns *s,*p;
+  behavior A:
+  assumes  H(*s);
+  requires P(*s);
+  ensures  Q(*s);
+*/
+int f(int *s);
+
+int g(int *s) {
+  int r = f(s);
+  /*@ assert W(*s); */
+  return r;
+}
diff --git a/src/plugins/wp/tests/wp_acsl/oracle/init_value.0.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle/init_value.0.res.oracle
index 5c44d6289ed42523daac49a6eff9c7d7982e3573..cbdaaf5b2b7be277b720039c917f78cfc8b2e51c 100644
--- a/src/plugins/wp/tests/wp_acsl/oracle/init_value.0.res.oracle
+++ b/src/plugins/wp/tests/wp_acsl/oracle/init_value.0.res.oracle
@@ -1,7 +1,13 @@
-# frama-c -wp -wp-no-let [...]
+# frama-c -wp [...]
 [kernel] Parsing init_value.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] Warning: Missing RTE guards
+[wp:union] init_value.i:61: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
+[wp:union] init_value.i:40: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
 ------------------------------------------------------------
   Function fa1
 ------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_acsl/oracle/init_value.1.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle/init_value.1.res.oracle
index 821291b40ccce48898653fb99fb582b4c1811661..50f2495c6a01090bc6531f526007a7beb512f303 100644
--- a/src/plugins/wp/tests/wp_acsl/oracle/init_value.1.res.oracle
+++ b/src/plugins/wp/tests/wp_acsl/oracle/init_value.1.res.oracle
@@ -1,7 +1,16 @@
-# frama-c -wp -wp-no-let [...]
+# frama-c -wp [...]
 [kernel] Parsing init_value.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] Warning: Missing RTE guards
+[wp:union] init_value.i:73: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
+[wp:union] init_value.i:72: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
+[wp:union] init_value.i:40: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
 ------------------------------------------------------------
   Function fa1
 ------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_acsl/oracle/label.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle/label.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..427d93afec44d7f58627b2d7bb0d13dac5c7f865
--- /dev/null
+++ b/src/plugins/wp/tests/wp_acsl/oracle/label.res.oracle
@@ -0,0 +1,47 @@
+# frama-c -wp [...]
+[kernel] Parsing label.i (no preprocessing)
+[wp] Running WP plugin...
+[wp] Warning: Missing RTE guards
+------------------------------------------------------------
+  Function g
+------------------------------------------------------------
+
+Goal Assertion (file label.i, line 27):
+Let x = Mint_0[s].
+Let m = Mint_0[p <- v][s <- v_1].
+Assume {
+  Type: is_sint32(v_1) /\ is_sint32(x).
+  (* Heap *)
+  Type: (region(p.base) <= 0) /\ (region(s.base) <= 0).
+  (* Call 'f' *)
+  Have: ((P_H(Mint_0, p, x) -> P_P(Mint_0, p, x))) /\
+      ((P_H(Mint_0, p, x) -> P_Q(m, p, v_1))).
+}
+Prove: P_W(m, p, v_1).
+
+------------------------------------------------------------
+
+Goal Instance of 'Pre-condition for 'A' (file label.i, line 20) in 'f'' in 'g' at initialization of 'r' (file label.i, line 26)
+:
+Let x = Mint_0[s].
+Assume {
+  Type: is_sint32(x).
+  (* Heap *)
+  Type: (region(p.base) <= 0) /\ (region(s.base) <= 0).
+  (* Goal *)
+  When: P_H(Mint_0, p, x).
+}
+Prove: P_P(Mint_0, p, x).
+
+------------------------------------------------------------
+[wp] label.i:23: Warning: 
+  Memory model hypotheses for function 'f':
+  /*@ behavior wp_typed:
+        requires \separated(p, &p);
+        requires \separated(s, &p); */
+  int f(int *s);
+[wp] label.i:25: Warning: 
+  Memory model hypotheses for function 'g':
+  /*@ behavior wp_typed:
+        requires \separated(s, &p); */
+  int g(int *s);
diff --git a/src/plugins/wp/tests/wp_acsl/oracle/poly.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle/poly.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..4c53a07ae903fe25075c2748defee28369a187bd
--- /dev/null
+++ b/src/plugins/wp/tests/wp_acsl/oracle/poly.res.oracle
@@ -0,0 +1,60 @@
+# frama-c -wp [...]
+[kernel] Parsing poly.c (with preprocessing)
+[wp] Running WP plugin...
+[wp] Warning: Missing RTE guards
+------------------------------------------------------------
+  Global
+------------------------------------------------------------
+
+Lemma test2_ko:
+Prove: (L_x_bar i_0 s_0)!=(concat (elt i_0) s_0)
+
+------------------------------------------------------------
+
+Lemma test2_ok:
+Prove: (L_x_bar i_0 s_0)=(concat (elt i_0) s_0)
+
+------------------------------------------------------------
+
+Lemma test_ko:
+Prove: (L_bar i_0 s_0)!=(concat (elt i_0) s_0)
+
+------------------------------------------------------------
+
+Lemma test_ok:
+Prove: (L_bar i_0 s_0)=(concat (elt i_0) s_0)
+
+------------------------------------------------------------
+
+Lemma testp2_ko:
+Prove: (L_x_foo a_0 s_0)!=(concat (elt a_0) s_0)
+
+------------------------------------------------------------
+
+Lemma testp2_ok:
+Prove: (L_x_foo a_0 s_0)=(concat (elt a_0) s_0)
+
+------------------------------------------------------------
+
+Lemma testp_ko:
+Prove: (L_foo a_0 s_0)!=(concat (elt a_0) s_0)
+
+------------------------------------------------------------
+
+Lemma testp_ok:
+Prove: (L_foo a_0 s_0)=(concat (elt a_0) s_0)
+
+------------------------------------------------------------
+------------------------------------------------------------
+  Function main
+------------------------------------------------------------
+
+Goal Check 'NotP_ok' (file poly.c, line 57):
+Prove: !P_P(1, [ 1 ]).
+
+------------------------------------------------------------
+
+Goal Check 'Y_ko' (file poly.c, line 58):
+Prove: P_Y(1, [ 1 ]).
+
+------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_acsl/oracle/struct_fields.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle/struct_fields.res.oracle
index 2aa95174028d023e0f7831b5cb8d8e0656e045f2..4a295addbe1c7f429f1a591003431cd4f65f7e09 100644
--- a/src/plugins/wp/tests/wp_acsl/oracle/struct_fields.res.oracle
+++ b/src/plugins/wp/tests/wp_acsl/oracle/struct_fields.res.oracle
@@ -1,4 +1,4 @@
-# frama-c -wp -wp-rte -wp-no-let [...]
+# frama-c -wp -wp-rte [...]
 [kernel] Parsing struct_fields.i (no preprocessing)
 [wp] Running WP plugin...
 [rte:annot] annotating function foo
diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/assigned_initialized_memvar.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle_qualif/assigned_initialized_memvar.res.oracle
index 587c090f8284138bd0a5aa71eb6be18c01c8ca00..dacc5c6bc9bf9488e22eceb94ca77ba10b4bb5db 100644
--- a/src/plugins/wp/tests/wp_acsl/oracle_qualif/assigned_initialized_memvar.res.oracle
+++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/assigned_initialized_memvar.res.oracle
@@ -23,16 +23,16 @@
 [wp] [Valid] typed_descr_loop_invariant_CHECK_established (Alt-Ergo) (Cached)
 [wp] [Valid] typed_descr_check_CHECK (Qed)
 [wp] [Valid] typed_descr_loop_assigns_part1 (Qed)
-[wp] [Valid] typed_descr_loop_assigns_part2 (Alt-Ergo) (Cached)
+[wp] [Unsuccess] typed_descr_loop_assigns_part2 (Alt-Ergo) (Cached)
 [wp] [Valid] typed_descr_loop_assigns_part3 (Qed)
 [wp] [Valid] typed_descr_loop_assigns_part4 (Qed)
 [wp] [Valid] typed_descr_loop_assigns_part5 (Qed)
 [wp] [Unsuccess] typed_comp_check_FAILS (Alt-Ergo) (Cached)
 [wp] [Valid] typed_comp_loop_assigns (Qed)
-[wp] Proved goals:   22 / 26
+[wp] Proved goals:   21 / 26
   Qed:            15
-  Alt-Ergo:        7
-  Unsuccess:       4
+  Alt-Ergo:        6
+  Unsuccess:       5
 ------------------------------------------------------------
  Functions                 WP     Alt-Ergo  Total   Success
   initialize                2        2        4       100%
@@ -40,6 +40,6 @@
   field                     1        -        2      50.0%
   array                     1        -        2      50.0%
   index                     2        -        3      66.7%
-  descr                     5        3        8       100%
+  descr                     5        2        8      87.5%
   comp                      1        -        2      50.0%
 ------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value.0.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value.0.res.oracle
index e7b468f7aee0e722570ffd9fe0f74c3a2a093fef..63575b9739f22b3ecee9973c5fa0acf9fcbcf694 100644
--- a/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value.0.res.oracle
+++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value.0.res.oracle
@@ -2,6 +2,12 @@
 [kernel] Parsing init_value.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] Warning: Missing RTE guards
+[wp:union] init_value.i:61: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
+[wp:union] init_value.i:40: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
 [wp] 24 goals scheduled
 [wp] [Valid] typed_main_requires_qed_ok_Struct_Simple_a (Qed)
 [wp] [Valid] typed_main_requires_qed_ok_Struct_Simple_b (Qed)
diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value.1.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value.1.res.oracle
index d10bff93b408b63526b401315b429d83248c495f..11b2e62f8964957835ca65dc89bf4cadd819b43c 100644
--- a/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value.1.res.oracle
+++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value.1.res.oracle
@@ -2,6 +2,15 @@
 [kernel] Parsing init_value.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] Warning: Missing RTE guards
+[wp:union] init_value.i:73: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
+[wp:union] init_value.i:72: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
+[wp:union] init_value.i:40: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
 [wp] 18 goals scheduled
 [wp] [Unsuccess] typed_main_ko_requires_qed_ko_Sc_eq_ko (Alt-Ergo) (Cached)
 [wp] [Unsuccess] typed_main_ko_requires_qed_ko_Sc_t (Alt-Ergo) (Cached)
diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/initialized_memvar.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle_qualif/initialized_memvar.res.oracle
index 16d71d9dd45c9a62045735bcb2c47c7a779d5b8f..3ef66a3ca21b36268cc80de2cdd8f523f750f659 100644
--- a/src/plugins/wp/tests/wp_acsl/oracle_qualif/initialized_memvar.res.oracle
+++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/initialized_memvar.res.oracle
@@ -75,15 +75,14 @@
 [wp] [Valid] typed_complex_struct_check_qed_ok_16 (Qed)
 [wp] [Valid] typed_complex_struct_check_qed_ok_17 (Qed)
 [wp] [Valid] typed_complex_struct_check_qed_ok_18 (Qed)
-[wp] [Valid] typed_complex_struct_check_provable (Tactic) (Qed 2/2)
+[wp] [Valid] typed_complex_struct_check_provable (Alt-Ergo) (Cached)
 [wp] Proved goals:   62 / 73
   Qed:            52
-  Script:          1 (Tactic) (Qed 2/2)
-  Alt-Ergo:        9
+  Alt-Ergo:       10
   Unsuccess:      11
 ------------------------------------------------------------
  Functions                 WP     Alt-Ergo  Total   Success
   globals                  13        7       31      64.5%
   locals                   21        2       23       100%
-  complex_struct           18        -       19       100%
+  complex_struct           18        1       19       100%
 ------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/poly.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle_qualif/poly.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..ee9a03a210dc77c43054b1c3c8b54f0b1ba13b63
--- /dev/null
+++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/poly.res.oracle
@@ -0,0 +1,25 @@
+# frama-c -wp [...]
+[kernel] Parsing poly.c (with preprocessing)
+[wp] Running WP plugin...
+[wp] Warning: Missing RTE guards
+[wp] 10 goals scheduled
+[wp] [Unsuccess] typed_check_lemma_test2_ko (Alt-Ergo) (Cached)
+[wp] [Valid] typed_check_lemma_test2_ok (Alt-Ergo) (Cached)
+[wp] [Unsuccess] typed_check_lemma_test_ko (Alt-Ergo) (Cached)
+[wp] [Valid] typed_check_lemma_test_ok (Alt-Ergo) (Cached)
+[wp] [Unsuccess] typed_check_lemma_testp2_ko (Alt-Ergo) (Cached)
+[wp] [Valid] typed_check_lemma_testp2_ok (Alt-Ergo) (Cached)
+[wp] [Unsuccess] typed_check_lemma_testp_ko (Alt-Ergo) (Cached)
+[wp] [Valid] typed_check_lemma_testp_ok (Alt-Ergo) (Cached)
+[wp] [Valid] typed_main_check_NotP_ok (Alt-Ergo) (Cached)
+[wp] [Unsuccess] typed_main_check_Y_ko (Alt-Ergo) (Cached)
+[wp] Proved goals:    5 / 10
+  Alt-Ergo:        5
+  Unsuccess:       5
+------------------------------------------------------------
+ Axiomatics                WP     Alt-Ergo  Total   Success
+  Lemma                     -        4        8      50.0%
+------------------------------------------------------------
+ Functions                 WP     Alt-Ergo  Total   Success
+  main                      -        1        2      50.0%
+------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_acsl/poly.c b/src/plugins/wp/tests/wp_acsl/poly.c
new file mode 100644
index 0000000000000000000000000000000000000000..db1394fc2775303f2193a9a2b752c7347d29dc3e
--- /dev/null
+++ b/src/plugins/wp/tests/wp_acsl/poly.c
@@ -0,0 +1,59 @@
+/*@ logic \list<A> foo<A> (A i, \list<A> s) = \Cons (i, s);
+
+    logic \list<integer> bar (integer i, \list<integer> s) =
+      foo(i, s);
+
+    check lemma test_ok: \forall integer i; \forall \list<integer> s;
+      bar (i, s) == \Cons (i, s);
+
+    check lemma test_ko: \forall integer i; \forall \list<integer> s;
+      bar (i, s) != \Cons (i, s);
+
+    check lemma testp_ok <A>: \forall A a; \forall \list<A> s;
+      foo (a, s) == \Cons (a, s);
+
+    check lemma testp_ko <A>: \forall A a; \forall \list<A> s;
+      foo (a, s) != \Cons (a, s);
+*/
+
+/*@ axiomatic X {
+      logic \list<A> x_foo<A>(A i, \list<A> s) reads \nothing ;
+      logic \list<integer> x_bar (integer i, \list<integer> s) reads \nothing ;
+
+      axiom x_foo_value<A>:
+        \forall A i, \list<A> s ;
+          x_foo(i, s) == \Cons(i, s) ;
+
+      axiom x_bar_value:
+        \forall integer i, \list<integer> s ;
+          x_bar(i, s) == x_foo(i, s) ;
+    }
+
+   check lemma test2_ok: \forall integer i; \forall \list<integer> s;
+      x_bar (i, s) == \Cons (i, s);
+
+    check lemma test2_ko: \forall integer i; \forall \list<integer> s;
+      x_bar (i, s) != \Cons (i, s);
+
+    check lemma testp2_ok <A>: \forall A a; \forall \list<A> s;
+      x_foo (a, s) == \Cons (a, s);
+
+    check lemma testp2_ko <A>: \forall A a; \forall \list<A> s;
+      x_foo (a, s) != \Cons (a, s);
+*/
+
+/*@ inductive P<A>(A i, \list<A> s){
+    case one<B>:
+      \forall B b, \list<B> s ; \Cons(b, s) == [| b |] ==> P(b, s);
+    }
+*/
+
+/*@ axiomatic Y {
+      predicate Y<A>(A i, \list<A> s);
+    }
+*/
+
+int main(void){
+  //@ check NotP_ok: !P(1, [| 1 |]) ;
+  //@ check Y_ko: Y(1, [| 1 |]) ;
+}
diff --git a/src/plugins/wp/tests/wp_bts/oracle_qualif/bts0843.res.oracle b/src/plugins/wp/tests/wp_bts/oracle_qualif/bts0843.res.oracle
index f95573ce220c8600bf02ea59a7baaba4783fd77e..0d6c49e91c2fd640733d1b5215eed5091410931b 100644
--- a/src/plugins/wp/tests/wp_bts/oracle_qualif/bts0843.res.oracle
+++ b/src/plugins/wp/tests/wp_bts/oracle_qualif/bts0843.res.oracle
@@ -4,8 +4,8 @@
 [wp] Warning: Missing RTE guards
 [wp] 4 goals scheduled
 [wp] [Valid] typed_f3_assigns (Qed)
-[wp] [Valid] typed_g3_assigns_exit (Alt-Ergo) (Trivial)
-[wp] [Valid] typed_g3_assigns_normal (Alt-Ergo) (Trivial)
+[wp] [Valid] typed_g3_assigns_exit (Alt-Ergo) (Cached)
+[wp] [Valid] typed_g3_assigns_normal (Alt-Ergo) (Cached)
 [wp] [Valid] typed_g3_call_f3_requires (Qed)
 [wp] Proved goals:    4 / 4
   Qed:             2
diff --git a/src/plugins/wp/tests/wp_gallery/binary-multiplication.0.session_qualif/script/BinaryMultiplication_loop_invariant_inv1_ok_preserved.json b/src/plugins/wp/tests/wp_gallery/binary-multiplication.0.session_qualif/script/BinaryMultiplication_loop_invariant_inv1_ok_preserved.json
deleted file mode 100644
index a9679b500c90b55ba77f83446cce7da4423edf0c..0000000000000000000000000000000000000000
--- a/src/plugins/wp/tests/wp_gallery/binary-multiplication.0.session_qualif/script/BinaryMultiplication_loop_invariant_inv1_ok_preserved.json
+++ /dev/null
@@ -1,61 +0,0 @@
-[ { "header": "Range", "tactic": "Wp.range",
-    "params": { "inf": 0, "sup": 1 },
-    "select": { "select": "inside-step", "at": 18, "kind": "have",
-                "occur": 0, "target": "b_1 mod 2", "pattern": "%$b2" },
-    "children": { "Lower 0": [ { "header": "Overflow",
-                                 "tactic": "Wp.overflow", "params": {},
-                                 "select": { "select": "inside-goal",
-                                             "occur": 0,
-                                             "target": "(to_uint64 (2*x_1))",
-                                             "pattern": "to_uint64.2$x" },
-                                 "children": { "In-Range": [ { "prover": "Alt-Ergo:2.2.0",
-                                                               "verdict": "valid",
-                                                               "time": 5.0522,
-                                                               "steps": 47 } ],
-                                               "Lower": [ { "prover": "qed",
-                                                            "verdict": "valid" } ],
-                                               "Upper": [ { "prover": "Alt-Ergo:2.2.0",
-                                                            "verdict": "valid",
-                                                            "time": 4.8984,
-                                                            "steps": 48 } ] } } ],
-                  "Value 0": [ { "header": "Overflow",
-                                 "tactic": "Wp.overflow", "params": {},
-                                 "select": { "select": "inside-step",
-                                             "at": 3, "kind": "have",
-                                             "occur": 0,
-                                             "target": "(to_uint64 (a_1*b_3))",
-                                             "pattern": "to_uint64*$a$b" },
-                                 "children": { "In-Range": [ { "prover": "Alt-Ergo:2.2.0",
-                                                               "verdict": "valid",
-                                                               "time": 5.0366,
-                                                               "steps": 181 } ],
-                                               "Lower": [ { "prover": "Alt-Ergo:2.2.0",
-                                                            "verdict": "valid",
-                                                            "time": 4.9686,
-                                                            "steps": 42 } ],
-                                               "Upper": [ { "prover": "Alt-Ergo:2.2.0",
-                                                            "verdict": "valid",
-                                                            "time": 4.9181,
-                                                            "steps": 42 } ] } } ],
-                  "Value 1": [ { "header": "Overflow",
-                                 "tactic": "Wp.overflow", "params": {},
-                                 "select": { "select": "inside-step",
-                                             "at": 3, "kind": "have",
-                                             "occur": 0,
-                                             "target": "(to_uint64 (a_1*b_3))",
-                                             "pattern": "to_uint64*$a$b" },
-                                 "children": { "In-Range": [ { "prover": "Alt-Ergo:2.2.0",
-                                                               "verdict": "valid",
-                                                               "time": 5.0078,
-                                                               "steps": 218 } ],
-                                               "Lower": [ { "prover": "Alt-Ergo:2.2.0",
-                                                            "verdict": "valid",
-                                                            "time": 4.7914,
-                                                            "steps": 45 } ],
-                                               "Upper": [ { "prover": "Alt-Ergo:2.2.0",
-                                                            "verdict": "valid",
-                                                            "time": 4.8087,
-                                                            "steps": 45 } ] } } ],
-                  "Upper 1": [ { "prover": "Alt-Ergo:2.2.0",
-                                 "verdict": "valid", "time": 4.9897,
-                                 "steps": 48 } ] } } ]
diff --git a/src/plugins/wp/tests/wp_gallery/binary-multiplication.c b/src/plugins/wp/tests/wp_gallery/binary-multiplication.c
index 26c0459f04acd1eb51b56e24764c26360ba62f6d..a02aa8b163627540a577066678c4599c8f894fb1 100644
--- a/src/plugins/wp/tests/wp_gallery/binary-multiplication.c
+++ b/src/plugins/wp/tests/wp_gallery/binary-multiplication.c
@@ -3,7 +3,6 @@
 */
 
 /* run.config_qualif
-   DEPS: @PTEST_DEPS@ @WP_SESSION@/script/BinaryMultiplication_*.json
    OPT: -wp-rte -wp-prover=alt-ergo,script -wp-prop=-lack @USING_WP_SESSION@
 */
 
@@ -15,7 +14,7 @@ typedef unsigned long long uint64_t ;
 /*@ axiomatic mult {
   @ lemma sizeof_ok: ok: sizeof(uint64_t) == 2*sizeof(uint32_t);
 
-  @ lemma ax1: lack: \forall integer x, y; 0<x  && 0<y ==> 0 <= 2*x*(y/2) <= x*y;
+  @ lemma ax1:   ok: \forall integer x, y; 0<x  && 0<y ==> 0 <= 2*x*(y/2) <= x*y;
 
   @ lemma ax2: lack: \forall integer x, y; (uint64_t)(x * ((uint64_t)y)) == (uint64_t)(x*y) ;
   @ lemma ax3: lack: \forall integer x, y; (uint64_t)(x + ((uint64_t)y)) == (uint64_t)(x+y) ;
@@ -44,7 +43,7 @@ uint64_t BinaryMultiplication (uint32_t a, uint32_t b) {
       //@ assert a4: ok: ((b%2) != 0) ==> 2*x*(b/2) + x == x*b;
       //@ assert a5: ok: ((b%2) == 0) ==> 2*x*(b/2)     == x*b;
       if (b%2) r=r+x;
-      //@ assert a6: lack: ok_z3: r+2*x*(b/2) == \at(a*b, Pre);
+      //@ assert a6: ok: r+2*x*(b/2) == \at(a*b, Pre);
       b=b/2;
       if (b==0) break;
       x=x*2;
diff --git a/src/plugins/wp/tests/wp_gallery/dune b/src/plugins/wp/tests/wp_gallery/dune
deleted file mode 100644
index 4e2c8b817fd365d5ffb809779a7f6bc45886160d..0000000000000000000000000000000000000000
--- a/src/plugins/wp/tests/wp_gallery/dune
+++ /dev/null
@@ -1,3 +0,0 @@
-(subdir
- result_qualif/binary-multiplication.0.session_qualif/script
- (copy_files ../../../binary-multiplication.0.session_qualif/script/*))
diff --git a/src/plugins/wp/tests/wp_gallery/oracle/binary-multiplication.res.oracle b/src/plugins/wp/tests/wp_gallery/oracle/binary-multiplication.res.oracle
index f1fdbe0b4cc752ffa0732f9e9ad4881d6e4b515c..ed79c05926d010358c98d1d852ec33c1f873823b 100644
--- a/src/plugins/wp/tests/wp_gallery/oracle/binary-multiplication.res.oracle
+++ b/src/plugins/wp/tests/wp_gallery/oracle/binary-multiplication.res.oracle
@@ -2,7 +2,7 @@
 [kernel] Parsing binary-multiplication.c (with preprocessing)
 [wp] Running WP plugin...
 [rte:annot] annotating function BinaryMultiplication
-[wp] Goal typed_lemma_ax1_lack : not tried
+[wp] Goal typed_lemma_ax1_ok : not tried
 [wp] Goal typed_lemma_ax2_lack : not tried
 [wp] Goal typed_lemma_ax3_lack : not tried
 [wp] Goal typed_lemma_ax4_ok : not tried
@@ -19,7 +19,7 @@
 [wp] Goal typed_BinaryMultiplication_assert_a3_ok : not tried
 [wp] Goal typed_BinaryMultiplication_assert_a4_ok : not tried
 [wp] Goal typed_BinaryMultiplication_assert_a5_ok : not tried
-[wp] Goal typed_BinaryMultiplication_assert_a6_lack_ok_z3 : not tried
+[wp] Goal typed_BinaryMultiplication_assert_a6_ok : not tried
 [wp] Goal typed_BinaryMultiplication_loop_assigns : trivial
 [wp] Goal typed_BinaryMultiplication_loop_variant_decrease : not tried
 [wp] Goal typed_BinaryMultiplication_loop_variant_positive : not tried
diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/binary-multiplication.res.oracle b/src/plugins/wp/tests/wp_gallery/oracle_qualif/binary-multiplication.res.oracle
index 7026644d5471d6f61f57894b18b79b080c99b6ce..366438d9c4439eabb1dbc454292844b6f823170a 100644
--- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/binary-multiplication.res.oracle
+++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/binary-multiplication.res.oracle
@@ -2,13 +2,15 @@
 [kernel] Parsing binary-multiplication.c (with preprocessing)
 [wp] Running WP plugin...
 [rte:annot] annotating function BinaryMultiplication
-[wp] 17 goals scheduled
+[wp] 19 goals scheduled
+[wp] [Valid] typed_lemma_ax1_ok (Alt-Ergo) (Cached)
 [wp] [Valid] typed_lemma_ax4_ok (Alt-Ergo) (Cached)
 [wp] [Valid] typed_lemma_ax5_ok (Alt-Ergo) (Cached)
 [wp] [Valid] typed_lemma_ax7_ok (Alt-Ergo) (Cached)
 [wp] [Valid] typed_lemma_sizeof_ok_ok (Qed)
 [wp] [Valid] typed_BinaryMultiplication_ensures_product (Alt-Ergo) (Cached)
 [wp] [Valid] typed_BinaryMultiplication_assert_a1_ok_deductible (Alt-Ergo) (Cached)
+[wp] [Valid] typed_BinaryMultiplication_loop_invariant_inv1_ok_preserved (Alt-Ergo) (Cached)
 [wp] [Valid] typed_BinaryMultiplication_loop_invariant_inv1_ok_established (Qed)
 [wp] [Valid] typed_BinaryMultiplication_loop_invariant_inv2_ok_preserved (Alt-Ergo) (Cached)
 [wp] [Valid] typed_BinaryMultiplication_loop_invariant_inv2_ok_established (Alt-Ergo) (Cached)
@@ -16,18 +18,17 @@
 [wp] [Valid] typed_BinaryMultiplication_assert_a3_ok (Alt-Ergo) (Cached)
 [wp] [Valid] typed_BinaryMultiplication_assert_a4_ok (Alt-Ergo) (Cached)
 [wp] [Valid] typed_BinaryMultiplication_assert_a5_ok (Alt-Ergo) (Cached)
+[wp] [Valid] typed_BinaryMultiplication_assert_a6_ok (Alt-Ergo) (Cached)
 [wp] [Valid] typed_BinaryMultiplication_loop_assigns (Qed)
 [wp] [Valid] typed_BinaryMultiplication_loop_variant_decrease (Alt-Ergo) (Cached)
 [wp] [Valid] typed_BinaryMultiplication_loop_variant_positive (Qed)
-[wp] [Valid] typed_BinaryMultiplication_loop_invariant_inv1_ok_preserved (Tactics 4) (Qed 1/10) (Alt-Ergo 9/10) (Cached)
-[wp] Proved goals:   17 / 17
+[wp] Proved goals:   19 / 19
   Qed:             4
-  Script:          1 (Tactics 4) (Qed 1/10) (Alt-Ergo 9/10) (Cached)
-  Alt-Ergo:       12
+  Alt-Ergo:       15
 ------------------------------------------------------------
  Axiomatics                WP     Alt-Ergo  Total   Success
-  Axiomatic mult            1        3        4       100%
+  Axiomatic mult            1        4        5       100%
 ------------------------------------------------------------
  Functions                 WP     Alt-Ergo  Total   Success
-  BinaryMultiplication      3        9       13       100%
+  BinaryMultiplication      3       11       14       100%
 ------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_hoare/oracle/dispatch_var2.0.res.oracle b/src/plugins/wp/tests/wp_hoare/oracle/dispatch_var2.0.res.oracle
index 4024b490fe730d706edd299a9b9b6c9e00510831..e8edfb10af666d6ddb4b08c1883440d4f0e540e9 100644
--- a/src/plugins/wp/tests/wp_hoare/oracle/dispatch_var2.0.res.oracle
+++ b/src/plugins/wp/tests/wp_hoare/oracle/dispatch_var2.0.res.oracle
@@ -1,4 +1,4 @@
-# frama-c -wp -wp-model 'Typed (Ref)' -wp-no-let [...]
+# frama-c -wp -wp-model 'Typed (Ref)' [...]
 [kernel] Parsing dispatch_var2.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] Warning: Missing RTE guards
diff --git a/src/plugins/wp/tests/wp_hoare/oracle_qualif/dispatch_var2.0.res.oracle b/src/plugins/wp/tests/wp_hoare/oracle_qualif/dispatch_var2.0.res.oracle
index b4a4eb8afb2222372e930c8becc2af080a8488ef..63e7e9f7e76ac58aa09826b19ed706ed2b0520cf 100644
--- a/src/plugins/wp/tests/wp_hoare/oracle_qualif/dispatch_var2.0.res.oracle
+++ b/src/plugins/wp/tests/wp_hoare/oracle_qualif/dispatch_var2.0.res.oracle
@@ -1,4 +1,4 @@
-# frama-c -wp -wp-model 'Typed (Ref)' -wp-no-let [...]
+# frama-c -wp -wp-model 'Typed (Ref)' [...]
 [kernel] Parsing dispatch_var2.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] Warning: Missing RTE guards
diff --git a/src/plugins/wp/tests/wp_plugin/bitmask0x8000.0.session_qualif/script/lemma_res_n.json b/src/plugins/wp/tests/wp_plugin/bitmask0x8000.0.session_qualif/script/lemma_res_n.json
index ce1db3baf849bcda6d5c7bc45ce2fad9d913cc87..7d837c3c45aefca935c29158827aa3c9cb926857 100644
--- a/src/plugins/wp/tests/wp_plugin/bitmask0x8000.0.session_qualif/script/lemma_res_n.json
+++ b/src/plugins/wp/tests/wp_plugin/bitmask0x8000.0.session_qualif/script/lemma_res_n.json
@@ -1,8 +1,9 @@
-[ { "header": "Bit-Test Range", "tactic": "Wp.bittestrange", "params": {},
+[ { "prover": "script", "verdict": "valid", "time": 0.0204 },
+  { "header": "Bit-Test Range", "tactic": "Wp.bittestrange", "params": {},
     "select": { "select": "inside-step", "at": 1, "kind": "have", "occur": 0,
                 "target": "not (bit_test off_0 15)",
                 "pattern": "!bit_test$off15" },
     "children": { "Bit #15 (inf)": [ { "prover": "qed", "verdict": "valid" } ],
-                  "Bit #15 (sup)": [ { "prover": "Alt-Ergo:2.2.0",
-                                       "verdict": "valid", "time": 0.0174,
-                                       "steps": 32 } ] } } ]
+                  "Bit #15 (sup)": [ { "prover": "Alt-Ergo:2.4.2",
+                                       "verdict": "valid", "time": 0.0204,
+                                       "steps": 52 } ] } } ]
diff --git a/src/plugins/wp/tests/wp_plugin/bitmask0x8000.0.session_qualif/script/lemma_res_y.json b/src/plugins/wp/tests/wp_plugin/bitmask0x8000.0.session_qualif/script/lemma_res_y.json
index 6efc632858bf4117e91e9c9f8cb43ca24a57fcc7..85a816285388870ca9a5453014af405aae549ac5 100644
--- a/src/plugins/wp/tests/wp_plugin/bitmask0x8000.0.session_qualif/script/lemma_res_y.json
+++ b/src/plugins/wp/tests/wp_plugin/bitmask0x8000.0.session_qualif/script/lemma_res_y.json
@@ -1,8 +1,9 @@
-[ { "header": "Bit-Test Range", "tactic": "Wp.bittestrange", "params": {},
+[ { "prover": "script", "verdict": "valid", "time": 0.0194 },
+  { "header": "Bit-Test Range", "tactic": "Wp.bittestrange", "params": {},
     "select": { "select": "inside-step", "at": 1, "kind": "have", "occur": 0,
                 "target": "(bit_test off_0 15)",
                 "pattern": "bit_test$off15" },
-    "children": { "Bit #15 (inf)": [ { "prover": "Alt-Ergo:2.2.0",
-                                       "verdict": "valid", "time": 0.0166,
-                                       "steps": 32 } ],
+    "children": { "Bit #15 (inf)": [ { "prover": "Alt-Ergo:2.4.2",
+                                       "verdict": "valid", "time": 0.0194,
+                                       "steps": 52 } ],
                   "Bit #15 (sup)": [ { "prover": "qed", "verdict": "valid" } ] } } ]
diff --git a/src/plugins/wp/tests/wp_plugin/config.sh b/src/plugins/wp/tests/wp_plugin/config.sh
index d0f7c134c09979614f7908269d1d33e30e9dc8f1..de8bba4f29673ebd4f2af8b6285e07cb5a34a682 100755
--- a/src/plugins/wp/tests/wp_plugin/config.sh
+++ b/src/plugins/wp/tests/wp_plugin/config.sh
@@ -1,7 +1,7 @@
 #!/bin/sh
 
-ERGO=`alt-ergo -version`
-WHY3=`why3 --version`
+ERGO=$(alt-ergo --version)
+WHY3=$(why3 --version)
 
 echo "----------------------------------------------------------"
 echo "WP Requirements for Qualif Tests"
diff --git a/src/plugins/wp/tests/wp_plugin/math.i b/src/plugins/wp/tests/wp_plugin/math.i
index 53a3106b4c5a605686807ae0bf937daa3a0c65db..ee5b3f68102f0e7431b942ddb1f54d3abb689ff9 100644
--- a/src/plugins/wp/tests/wp_plugin/math.i
+++ b/src/plugins/wp/tests/wp_plugin/math.i
@@ -3,8 +3,8 @@
 */
 
 /* run.config_qualif
-   OPT: -wp-prover alt-ergo -wp-prop=-ko  -wp-timeout 100 -wp-steps 1500
-   OPT: -wp-prover alt-ergo -wp-prop=ko   -wp-timeout 100 -wp-steps 10
+   OPT: -wp-prover alt-ergo -wp-prop=-ko
+   OPT: -wp-prover alt-ergo -wp-prop=ko -wp-steps 10
 */
 
 // --------------------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_plugin/no_step_limit.conf b/src/plugins/wp/tests/wp_plugin/no_step_limit.conf
index 8431029cc72c4dc267bef9b413c03d74406ae297..b027de63b86182b44d982297506a0715de163531 100644
--- a/src/plugins/wp/tests/wp_plugin/no_step_limit.conf
+++ b/src/plugins/wp/tests/wp_plugin/no_step_limit.conf
@@ -6,8 +6,8 @@ running_provers_max = 2
 timelimit = 5
 
 [prover]
-command = "alt-ergo -timelimit %t %f"
-driver = "alt_ergo_2_2_0"
+command = "alt-ergo --timelimit %t %f"
+driver = "alt_ergo"
 in_place = false
 interactive = false
 name = "no-steps"
diff --git a/src/plugins/wp/tests/wp_plugin/no_step_limit.i b/src/plugins/wp/tests/wp_plugin/no_step_limit.i
index 874baf0c74f20fa9a2510a1cbc783138caedaf2a..569fecc3020f9ba4076e2c733b7c4f109bdac3d1 100644
--- a/src/plugins/wp/tests/wp_plugin/no_step_limit.i
+++ b/src/plugins/wp/tests/wp_plugin/no_step_limit.i
@@ -7,7 +7,7 @@
   OPT: -wp -wp-prover no-steps -wp-steps 10 -wp-timeout 1 -wp-cache none -wp-no-cache-env -wp-msg-key shell
 */
 
-// cache is locally deactivated to see the option
+// cache is locally deactivated to be sure that we call the prover
 
 /*@
   lemma truc: \false ;
diff --git a/src/plugins/wp/tests/wp_plugin/nth.i b/src/plugins/wp/tests/wp_plugin/nth.i
index 33236ef838299d9fff8a9616d03b62b76f261b9c..88491366a5ba6dc6e2092f577d26e26635d20578 100644
--- a/src/plugins/wp/tests/wp_plugin/nth.i
+++ b/src/plugins/wp/tests/wp_plugin/nth.i
@@ -83,14 +83,16 @@
   check lemma nth_repeat_3: ok: \nth ( ([| f(0), f(1), f(2), f(3) |] *^ 3) ^ [| f(12) |] , 12 ) ==  f(12);
   check lemma nth_repeat_4: ok: \nth ( ([| f(0), f(1), f(2), f(3) |] *^ 3) ^ [| f(12),f(13),f(14)|] ^ S, 13 ) ==  f(13);
 
-  lemma access_16_16: ok:
-  \forall integer k ; 0 <= k < 16 ==>
-    f(k)==\nth([| f(0), f(1), f(2),  f(3),  f(4),  f(5),  f(6),  f(7),
-                  f(8), f(9), f(10), f(11), f(12), f(13), f(14), f(15) |], k);
 
   lemma access_4_4: ok:
   \forall integer k ; 0 <= k < 4 ==>
-    f(k)==\nth([| f(0), f(1), f(2),  f(3) |], k);
+    f(k)==\nth([| f(0), f(1), f(2), f(3) |], k);
+
+  // Performance problem with Alt-Ergo, cvc4 & z3 are ok.
+  lemma access_8_8: ko:
+  \forall integer k ; 0 <= k < 6 ==>
+    f(k)==\nth([| f(0), f(1), f(2), f(3),
+                  f(4), f(5), f(6), f(7) |], k);
 
   lemma eq_repeat_concat_3: ok: (S *^ 3) == (S ^ S ^ S) ;
 
diff --git a/src/plugins/wp/tests/wp_plugin/oracle/bool.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle/bool.res.oracle
index 9f83df04d9f5f3ca44cb15ff7c72b6eb6ca4d3fc..916d7d88f9aadff39b4464b8fe1e785ef7762ada 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle/bool.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle/bool.res.oracle
@@ -1,4 +1,4 @@
-# frama-c -wp -wp-no-let [...]
+# frama-c -wp [...]
 [kernel] Parsing bool.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] Warning: Missing RTE guards
diff --git a/src/plugins/wp/tests/wp_plugin/oracle/dynamic.1.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle/dynamic.1.res.oracle
index 78ddf615c388fbb450e6f01f9deb175c6107177b..95d16f1f5457093aa994b77335a29b679251ca08 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle/dynamic.1.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle/dynamic.1.res.oracle
@@ -1,4 +1,4 @@
-# frama-c -wp -wp-no-let [...]
+# frama-c -wp [...]
 [kernel] Parsing dynamic.i (no preprocessing)
 [wp] Running WP plugin...
 [kernel:dyncalls] Computing dynamic calls.
diff --git a/src/plugins/wp/tests/wp_plugin/oracle/nth.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle/nth.res.oracle
index c93629cbb62d4b5fa92e4144cc23d6e0c1089cf1..3042f600a4b71ccf48ac6ebb5e178b17fd97c225 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle/nth.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle/nth.res.oracle
@@ -96,35 +96,33 @@ Prove: true
   Axiomatic 'Nth'
 ------------------------------------------------------------
 
-Lemma access_16_16:
-Prove: (0<=k_0) -> (k_0<=15)
+Lemma access_4_4:
+Prove: (0<=k_0) -> (k_0<=3)
        -> ((nth
-             (concat (elt (L_f 0)) (elt (L_f 1)) (elt (L_f 2)) (elt (L_f 3))
-               (elt (L_f 4)) (elt (L_f 5)) (elt (L_f 6)) (elt (L_f 7))
-               (elt (L_f 8)) (elt (L_f 9)) (elt (L_f 10)) (elt (L_f 11))
-               (elt (L_f 12)) (elt (L_f 13)) (elt (L_f 14)) (elt (L_f 15)))
+             (concat (elt (L_f 0)) (elt (L_f 1)) (elt (L_f 2)) (elt (L_f 3)))
              k_0)=(L_f k_0))
 
 ------------------------------------------------------------
 
-Lemma access_4_4:
-Assume: 'access_16_16'
-Prove: (0<=k_0) -> (k_0<=3)
+Lemma access_8_8:
+Assume: 'access_4_4'
+Prove: (0<=k_0) -> (k_0<=5)
        -> ((nth
-             (concat (elt (L_f 0)) (elt (L_f 1)) (elt (L_f 2)) (elt (L_f 3)))
-             k_0)=(L_f k_0))
+             (concat (elt (L_f 0)) (elt (L_f 1)) (elt (L_f 2)) (elt (L_f 3))
+               (elt (L_f 4)) (elt (L_f 5)) (elt (L_f 6)) (elt (L_f 7))) k_0)=
+           (L_f k_0))
 
 ------------------------------------------------------------
 
 Lemma access_repeat_concat_3:
-Assume: 'eq_repeat_concat_3' 'access_4_4' 'access_16_16'
+Assume: 'eq_repeat_concat_3' 'access_8_8' 'access_4_4'
 Prove: (0<=k_0) -> (k_0<(3*(length L_S)))
        -> ((nth (concat L_S L_S L_S) k_0)=(nth (repeat L_S 3) k_0))
 
 ------------------------------------------------------------
 
 Lemma eq_repeat_concat_3:
-Assume: 'access_4_4' 'access_16_16'
+Assume: 'access_8_8' 'access_4_4'
 Prove: true
 
 ------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/bool.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/bool.res.oracle
index 142edc4f0cf5a5c62c1e991a3b6ef2d7e1802877..80ce1585aa40e373b6a763e0313aa7362379c287 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/bool.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/bool.res.oracle
@@ -1,4 +1,4 @@
-# frama-c -wp -wp-no-let [...]
+# frama-c -wp [...]
 [kernel] Parsing bool.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] Warning: Missing RTE guards
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/config.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/config.res.oracle
index 97170530440a3845d5f2f211a8210288c2fe968d..872f60957845a4f288caf9656729b8c01337fdfb 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/config.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/config.res.oracle
@@ -1,7 +1,7 @@
 ----------------------------------------------------------
 WP Requirements for Qualif Tests
 ----------------------------------------------------------
-1. The Alt-Ergo theorem prover, version 2.2.0
+1. The Alt-Ergo theorem prover, version 2.4.2
 2. The Why3 platform, version 1.6.0
 3. The environment variable FRAMAC_WP_CACHEDIR is defined
 4. The environment variable FRAMAC_WP_CACHE is defined
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_call.2.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_call.2.res.oracle
index 81a4482c29daf7beee20bc107cd21a74967cd539..b14c7877833655b73d792637d3590c03ac47c185 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_call.2.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_call.2.res.oracle
@@ -1,4 +1,4 @@
-# frama-c -wp -wp-split [...]
+# frama-c -wp [...]
 [kernel] Parsing doomed_call.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] Warning: Missing RTE guards
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_dead.1.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_dead.1.res.oracle
index 79b0373da5e3574e35ac0322a24ca4698fa1044c..7af31c3fade31c46da6450fb0c3854db349c6566 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_dead.1.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_dead.1.res.oracle
@@ -1,4 +1,4 @@
-# frama-c -wp -wp-split -wp-steps 100 [...]
+# frama-c -wp -wp-steps 100 [...]
 [kernel] Parsing doomed_dead.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] Warning: Missing RTE guards
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/dynamic.1.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/dynamic.1.res.oracle
index 071c3882ef864c99746b31c65f61d79bd3750fe8..6a8654dd7d2de39d670103ad43abc2a9cd79692d 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/dynamic.1.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/dynamic.1.res.oracle
@@ -1,4 +1,4 @@
-# frama-c -wp -wp-no-let [...]
+# frama-c -wp [...]
 [kernel] Parsing dynamic.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] Warning: Missing RTE guards
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/fallback.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/fallback.res.oracle
index 439fab9b307931b975e697bb0cf2e8b7672fffbe..64b72dd87d8a2b06987d2ecd68d2073131bd47d9 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/fallback.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/fallback.res.oracle
@@ -2,7 +2,7 @@
 [kernel] Parsing fallback.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] Warning: Missing RTE guards
-[wp] Warning: Prover 'Alt-Ergo:1.2.0' not found, fallback to 'Alt-Ergo:2.2.0'
+[wp] Warning: Prover 'Alt-Ergo:1.2.0' not found, fallback to 'Alt-Ergo:2.4.2'
 [wp] 1 goal scheduled
 [wp] [Valid] typed_job_ensures (Alt-Ergo) (Cached)
 [wp] Proved goals:    1 / 1
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/math.0.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/math.0.res.oracle
index e48d5ca2e49ca5c7a548b7a861bff87d268acf30..e524c1cb1cb2d70a571f66dfe6902ba21b6f0eeb 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/math.0.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/math.0.res.oracle
@@ -1,4 +1,4 @@
-# frama-c -wp -wp-timeout 100 -wp-steps 1500 [...]
+# frama-c -wp [...]
 [kernel] Parsing math.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] Warning: Missing RTE guards
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/math.1.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/math.1.res.oracle
index fc8e2c09ad5ec29ca0ab3ddfb253427904cce81b..12b2a96e99f4d5f9d51037d6e9530a6db39d8391 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/math.1.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/math.1.res.oracle
@@ -1,4 +1,4 @@
-# frama-c -wp -wp-timeout 100 -wp-steps 10 [...]
+# frama-c -wp -wp-steps 10 [...]
 [kernel] Parsing math.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] Warning: Missing RTE guards
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/no_step_limit.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/no_step_limit.res.oracle
index 452e8047b202ff04ef91186ef6d26c207cc78dc8..0ad955337d7de65fff2945690804cd5a4d4f4b11 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/no_step_limit.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/no_step_limit.res.oracle
@@ -2,6 +2,7 @@
 [kernel] Parsing no_step_limit.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] 1 goal scheduled
+[wp] Warning: no-steps  does not support steps limit (ignored option)
 [wp] [Unsuccess] typed_lemma_truc (no-steps)
 [wp] Proved goals:    0 / 1
   Unsuccess:       1
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/nth.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/nth.res.oracle
index 1aeb2e63b01db6747367dd9c88cba0399224c93d..edb9844f6a4b1a158e205f172e3bd85ea2241b20 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/nth.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/nth.res.oracle
@@ -2,8 +2,8 @@
 [kernel] Parsing nth.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] 26 goals scheduled
-[wp] [Valid] typed_lemma_access_16_16_ok (Alt-Ergo) (Cached)
 [wp] [Valid] typed_lemma_access_4_4_ok (Alt-Ergo) (Cached)
+[wp] [Unsuccess] typed_lemma_access_8_8_ko (Alt-Ergo) (Cached)
 [wp] [Valid] typed_lemma_access_repeat_concat_3_ok_lack (Alt-Ergo) (Cached)
 [wp] [Valid] typed_check_lemma_constructor_elt_ok (Qed)
 [wp] [Valid] typed_lemma_eq_repeat_concat_3_ok (Qed)
@@ -28,13 +28,13 @@
 [wp] [Valid] typed_check_lemma_right_unfold_repeat1_ok (Qed)
 [wp] [Valid] typed_check_lemma_right_unfold_repeat2_ok (Qed)
 [wp] [Valid] typed_check_lemma_subsequence1_ok (Qed)
-[wp] Proved goals:   25 / 26
+[wp] Proved goals:   24 / 26
   Qed:            22
-  Alt-Ergo:        3
-  Unsuccess:       1
+  Alt-Ergo:        2
+  Unsuccess:       2
 ------------------------------------------------------------
  Axiomatics                WP     Alt-Ergo  Total   Success
   Axiomatic Equality       13        -       13       100%
   Axiomatic MkRepeat        4        -        4       100%
-  Axiomatic Nth             5        3        9      88.9%
+  Axiomatic Nth             5        2        9      77.8%
 ------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_plugin/unsigned.0.session_qualif/script/lemma_U32.json b/src/plugins/wp/tests/wp_plugin/unsigned.0.session_qualif/script/lemma_U32.json
index c4a3730943a5705f49d9a0510a3f8b28c275b328..1eb7da85a99959de78cab81e75af587c16b003e7 100644
--- a/src/plugins/wp/tests/wp_plugin/unsigned.0.session_qualif/script/lemma_U32.json
+++ b/src/plugins/wp/tests/wp_plugin/unsigned.0.session_qualif/script/lemma_U32.json
@@ -1,11 +1,9 @@
-[ { "prover": "Alt-Ergo:2.2.0", "verdict": "timeout", "time": 10. },
-  { "prover": "script", "verdict": "valid" },
+[ { "prover": "script", "verdict": "unknown" },
   { "header": "Bitwise Eq.", "tactic": "Wp.bitwised",
     "params": { "Wp.bitwised.range": 32 },
     "select": { "select": "clause-goal",
                 "target": "(land 4294967295 x_0)=x_0",
                 "pattern": "=land$x4294967295$x" },
-    "children": { "range": [ { "prover": "Alt-Ergo:2.2.0",
-                               "verdict": "valid", "time": 0.0054,
-                               "steps": 15 } ],
+    "children": { "range": [ { "prover": "Alt-Ergo:2.4.2",
+                               "verdict": "timeout", "time": 10. } ],
                   "bitwise": [ { "prover": "qed", "verdict": "valid" } ] } } ]
diff --git a/src/plugins/wp/tests/wp_tip/induction.0.session_qualif/script/lemma_ByInd.json b/src/plugins/wp/tests/wp_tip/induction.0.session_qualif/script/lemma_ByInd.json
index 77a4f51c832cb8e9d049e59dd20d0b4644788ff9..8b2dde4abb4656b6c0861116139230d62716131a 100644
--- a/src/plugins/wp/tests/wp_tip/induction.0.session_qualif/script/lemma_ByInd.json
+++ b/src/plugins/wp/tests/wp_tip/induction.0.session_qualif/script/lemma_ByInd.json
@@ -1,12 +1,13 @@
-[ { "header": "Induction", "tactic": "Wp.induction",
+[ { "prover": "script", "verdict": "valid", "time": 0.04 },
+  { "header": "Induction", "tactic": "Wp.induction",
     "params": { "base": { "select": "kint", "val": "0" } },
     "select": { "select": "inside-goal", "occur": 0, "target": "(L_f x_0)",
                 "pattern": "L_f$x" },
-    "children": { "Base": [ { "prover": "Alt-Ergo:2.2.0", "verdict": "valid",
-                              "time": 0.0074, "steps": 6 } ],
-                  "Induction (sup)": [ { "prover": "Alt-Ergo:2.2.0",
-                                         "verdict": "valid", "time": 0.0098,
-                                         "steps": 21 } ],
-                  "Induction (inf)": [ { "prover": "Alt-Ergo:2.2.0",
-                                         "verdict": "valid", "time": 0.0097,
-                                         "steps": 20 } ] } } ]
+    "children": { "Base": [ { "prover": "Alt-Ergo:2.4.2", "verdict": "valid",
+                              "time": 0.0035, "steps": 14 } ],
+                  "Induction (sup)": [ { "prover": "Alt-Ergo:2.4.2",
+                                         "verdict": "valid", "time": 0.0247,
+                                         "steps": 325 } ],
+                  "Induction (inf)": [ { "prover": "Alt-Ergo:2.4.2",
+                                         "verdict": "valid", "time": 0.0118,
+                                         "steps": 32 } ] } } ]
diff --git a/src/plugins/wp/tests/wp_tip/induction.1.session_qualif/script/lemma_ByInd.json b/src/plugins/wp/tests/wp_tip/induction.1.session_qualif/script/lemma_ByInd.json
index d5763f40f15dd0fb0e845177f6d42085f36486ca..475ea8fe40f40e261b057116b3796f55f5e84f28 100644
--- a/src/plugins/wp/tests/wp_tip/induction.1.session_qualif/script/lemma_ByInd.json
+++ b/src/plugins/wp/tests/wp_tip/induction.1.session_qualif/script/lemma_ByInd.json
@@ -1,12 +1,11 @@
-[ { "prover": "Alt-Ergo:2.2.0", "verdict": "unknown" },
-  { "prover": "script", "verdict": "unknown" },
+[ { "prover": "script", "verdict": "unknown" },
   { "header": "Induction", "tactic": "Wp.induction",
     "params": { "base": { "select": "kint", "val": "0" } },
     "select": { "select": "inside-goal", "occur": 0, "target": "x_0",
                 "pattern": "$x" },
-    "children": { "Base": [ { "prover": "Alt-Ergo:2.2.0",
-                              "verdict": "unknown" } ],
-                  "Induction (sup)": [ { "prover": "Alt-Ergo:2.2.0",
-                                         "verdict": "unknown" } ],
-                  "Induction (inf)": [ { "prover": "Alt-Ergo:2.2.0",
-                                         "verdict": "timeout", "time": 1. } ] } } ]
+    "children": { "Base": [ { "prover": "Alt-Ergo:2.4.2",
+                              "verdict": "timeout", "time": 10. } ],
+                  "Induction (sup)": [ { "prover": "Alt-Ergo:2.4.2",
+                                         "verdict": "timeout", "time": 10. } ],
+                  "Induction (inf)": [ { "prover": "Alt-Ergo:2.4.2",
+                                         "verdict": "timeout", "time": 10. } ] } } ]
diff --git a/src/plugins/wp/tests/wp_tip/induction.2.session_qualif/script/lemma_ByInd.json b/src/plugins/wp/tests/wp_tip/induction.2.session_qualif/script/lemma_ByInd.json
index 5e068a85c7f8f2ef58ef88d2b0b651607423e155..19e60ed0b607ee5b192a441d5d08ae2c86ed06af 100644
--- a/src/plugins/wp/tests/wp_tip/induction.2.session_qualif/script/lemma_ByInd.json
+++ b/src/plugins/wp/tests/wp_tip/induction.2.session_qualif/script/lemma_ByInd.json
@@ -1,12 +1,11 @@
-[ { "prover": "Alt-Ergo:2.2.0", "verdict": "unknown" },
-  { "prover": "script", "verdict": "unknown" },
+[ { "prover": "script", "verdict": "unknown" },
   { "header": "Induction", "tactic": "Wp.induction",
     "params": { "base": { "select": "kint", "val": "0" } },
     "select": { "select": "inside-goal", "occur": 0, "target": "y_0",
                 "pattern": "$y" },
-    "children": { "Base": [ { "prover": "Alt-Ergo:2.2.0",
-                              "verdict": "unknown" } ],
-                  "Induction (sup)": [ { "prover": "Alt-Ergo:2.2.0",
-                                         "verdict": "unknown" } ],
-                  "Induction (inf)": [ { "prover": "Alt-Ergo:2.2.0",
-                                         "verdict": "timeout", "time": 1. } ] } } ]
+    "children": { "Base": [ { "prover": "Alt-Ergo:2.4.2",
+                              "verdict": "timeout", "time": 10. } ],
+                  "Induction (sup)": [ { "prover": "Alt-Ergo:2.4.2",
+                                         "verdict": "timeout", "time": 10. } ],
+                  "Induction (inf)": [ { "prover": "Alt-Ergo:2.4.2",
+                                         "verdict": "timeout", "time": 10. } ] } } ]
diff --git a/src/plugins/wp/tests/wp_tip/oracle_qualif/proof.res.oracle b/src/plugins/wp/tests/wp_tip/oracle_qualif/proof.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..276f2354052a77a51a160cbd408812bcc194595a
--- /dev/null
+++ b/src/plugins/wp/tests/wp_tip/oracle_qualif/proof.res.oracle
@@ -0,0 +1,11 @@
+# frama-c -wp [...]
+[kernel] Parsing proof.i (no preprocessing)
+[wp] Running WP plugin...
+[wp] Warning: No goal generated
+------------------------------------------------------------
+/* Generated by Frama-C */
+/*@ strategy P1: \prover("alt-ergo"); */
+/*@ strategy P2: \prover(0.5); */
+/*@ strategy P3: \prover("alt-ergo",3.0); */
+/*@ strategy P4: P1, P2, P3, \default; */
+
diff --git a/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.0.res.oracle b/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.0.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..0bcfae5a92959b95342e01fa937cd88c40831ebe
--- /dev/null
+++ b/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.0.res.oracle
@@ -0,0 +1,28 @@
+# frama-c -wp [...]
+[kernel] Parsing strategy.c (with preprocessing)
+[wp] Running WP plugin...
+[wp] Warning: Missing RTE guards
+[wp] 2 goals scheduled
+[wp] [Unsuccess] typed_target_ensures (Alt-Ergo) (Cached)
+[wp] [Valid] typed_target_assigns (Qed)
+[wp] Proved goals:    1 / 2
+  Qed:             1
+  Unsuccess:       1
+------------------------------------------------------------
+  Function target
+------------------------------------------------------------
+
+Goal Post-condition (file strategy.c, line 46) in 'target':
+Assume {
+  Type: is_uint32(t) /\ is_uint32(x) /\ is_uint32(y) /\ is_uint32(z).
+  (* Pre-condition *)
+  Have: (t <= 999) /\ (x <= 999) /\ (y <= 999) /\ (z <= 999).
+}
+Prove: P_P(to_sint32(t + to_uint32(z + to_uint32(x + y)))).
+Prover Alt-Ergo returns Unsuccess
+
+------------------------------------------------------------
+------------------------------------------------------------
+ Functions                 WP     Alt-Ergo  Total   Success
+  target                    1        -        2      50.0%
+------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.1.res.oracle b/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..a439255effce75c9e03ad1957717ddcc7e77cf90
--- /dev/null
+++ b/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.1.res.oracle
@@ -0,0 +1,52 @@
+# frama-c -wp [...]
+[kernel] Parsing strategy.c (with preprocessing)
+[wp] Running WP plugin...
+[wp] Warning: Missing RTE guards
+[wp] 2 goals scheduled
+[wp] [Valid] typed_target_assigns (Qed)
+[wp] [Unsuccess] typed_target_ensures (Tactics 13)
+[wp] Proved goals:    1 / 2
+  Qed:             1
+  Unsuccess:       1
+------------------------------------------------------------
+  Function target
+------------------------------------------------------------
+
+Goal Post-condition (file strategy.c, line 46) in 'target':
+Assume {
+  Type: is_uint32(t) /\ is_uint32(x) /\ is_uint32(y) /\ is_uint32(z).
+  (* Pre-condition *)
+  Have: (t <= 999) /\ (x <= 999) /\ (y <= 999) /\ (z <= 999).
+}
+Prove: P_P(to_sint32(t + to_uint32(z + to_uint32(x + y)))).
+Prover Script returns Unsuccess
+
+------------------------------------------------------------
+Subgoal 1/1:
+ - Post-condition
+ - Overflow (In-Range)
+ - Overflow (In-Range)
+ - Overflow (In-Range)
+Goal Wp.Tactical.typed_target_ensures-12 (generated):
+Let x_1 = t + x + y + z.
+Let x_2 = x + y + z.
+Let x_3 = x + y.
+Assume {
+  Have: 0 <= x_3.
+  Have: x_3 <= 4294967295.
+  Have: 0 <= x_2.
+  Have: x_2 <= 4294967295.
+  Have: (-2147483648) <= x_1.
+  Have: x_1 <= 2147483647.
+  Type: is_uint32(t) /\ is_uint32(x) /\ is_uint32(y) /\ is_uint32(z).
+  (* Pre-condition *)
+  Have: (t <= 999) /\ (x <= 999) /\ (y <= 999) /\ (z <= 999).
+}
+Prove: P_P(x_1).
+Prover Alt-Ergo returns Unsuccess
+
+------------------------------------------------------------
+------------------------------------------------------------
+ Functions                 WP     Alt-Ergo  Total   Success
+  target                    1        -        2      50.0%
+------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.2.res.oracle b/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..ca5793fb1a1ba8e7da0c82f34edb192a2236e25c
--- /dev/null
+++ b/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.2.res.oracle
@@ -0,0 +1,52 @@
+# frama-c -wp [...]
+[kernel] Parsing strategy.c (with preprocessing)
+[wp] Running WP plugin...
+[wp] Warning: Missing RTE guards
+[wp] 2 goals scheduled
+[wp] [Valid] typed_target_assigns (Qed)
+[wp] [Unsuccess] typed_target_ensures (Tactics 3) (Alt-Ergo 4/4) (Cached)
+[wp] Proved goals:    1 / 2
+  Qed:             1
+  Unsuccess:       1
+------------------------------------------------------------
+  Function target
+------------------------------------------------------------
+
+Goal Post-condition (file strategy.c, line 46) in 'target':
+Assume {
+  Type: is_uint32(t) /\ is_uint32(x) /\ is_uint32(y) /\ is_uint32(z).
+  (* Pre-condition *)
+  Have: (t <= 999) /\ (x <= 999) /\ (y <= 999) /\ (z <= 999).
+}
+Prove: P_P(to_sint32(t + to_uint32(z + to_uint32(x + y)))).
+Prover Script returns Unsuccess
+
+------------------------------------------------------------
+Subgoal 1/1:
+ - Post-condition
+ - Overflow (In-Range)
+ - Overflow (In-Range)
+ - Overflow (In-Range)
+Goal Wp.Tactical.typed_target_ensures-6 (generated):
+Let x_1 = t + x + y + z.
+Let x_2 = x + y + z.
+Let x_3 = x + y.
+Assume {
+  Have: 0 <= x_3.
+  Have: x_3 <= 4294967295.
+  Have: 0 <= x_2.
+  Have: x_2 <= 4294967295.
+  Have: (-2147483648) <= x_1.
+  Have: x_1 <= 2147483647.
+  Type: is_uint32(t) /\ is_uint32(x) /\ is_uint32(y) /\ is_uint32(z).
+  (* Pre-condition *)
+  Have: (t <= 999) /\ (x <= 999) /\ (y <= 999) /\ (z <= 999).
+}
+Prove: P_P(x_1).
+Prover Alt-Ergo returns Unsuccess
+
+------------------------------------------------------------
+------------------------------------------------------------
+ Functions                 WP     Alt-Ergo  Total   Success
+  target                    1        -        2      50.0%
+------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.3.res.oracle b/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.3.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..ad30c792620a6ac36164a3de5f3a7eb8bcfff589
--- /dev/null
+++ b/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.3.res.oracle
@@ -0,0 +1,53 @@
+# frama-c -wp [...]
+[kernel] Parsing strategy.c (with preprocessing)
+[wp] Running WP plugin...
+[wp] Warning: Missing RTE guards
+[wp] 2 goals scheduled
+[wp] [Valid] typed_target_assigns (Qed)
+[wp] [Unsuccess] typed_target_ensures (Tactics 3) (Alt-Ergo 4/4) (Cached)
+[wp] Proved goals:    1 / 2
+  Qed:             1
+  Unsuccess:       1
+------------------------------------------------------------
+  Function target
+------------------------------------------------------------
+
+Goal Post-condition (file strategy.c, line 46) in 'target':
+Assume {
+  Type: is_uint32(t) /\ is_uint32(x) /\ is_uint32(y) /\ is_uint32(z).
+  (* Pre-condition *)
+  Have: (t <= 999) /\ (x <= 999) /\ (y <= 999) /\ (z <= 999).
+}
+Prove: P_P(to_sint32(t + to_uint32(z + to_uint32(x + y)))).
+Prover Alt-Ergo returns Unsuccess
+Prover Script returns Unsuccess
+
+------------------------------------------------------------
+Subgoal 1/1:
+ - Post-condition
+ - Overflow (In-Range)
+ - Overflow (In-Range)
+ - Overflow (In-Range)
+Goal Wp.Tactical.typed_target_ensures-6 (generated):
+Let x_1 = t + x + y + z.
+Let x_2 = x + y + z.
+Let x_3 = x + y.
+Assume {
+  Have: 0 <= x_3.
+  Have: x_3 <= 4294967295.
+  Have: 0 <= x_2.
+  Have: x_2 <= 4294967295.
+  Have: (-2147483648) <= x_1.
+  Have: x_1 <= 2147483647.
+  Type: is_uint32(t) /\ is_uint32(x) /\ is_uint32(y) /\ is_uint32(z).
+  (* Pre-condition *)
+  Have: (t <= 999) /\ (x <= 999) /\ (y <= 999) /\ (z <= 999).
+}
+Prove: P_P(x_1).
+Prover Alt-Ergo returns Unsuccess
+
+------------------------------------------------------------
+------------------------------------------------------------
+ Functions                 WP     Alt-Ergo  Total   Success
+  target                    1        -        2      50.0%
+------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_tip/overflow.0.session_qualif/script/lemma_j_incr_char.json b/src/plugins/wp/tests/wp_tip/overflow.0.session_qualif/script/lemma_j_incr_char.json
index 255539ba9f34b22d89852d5659ffc0969380c9f1..28f66b07060696d4cab811bb4b79ab4f08e7efa3 100644
--- a/src/plugins/wp/tests/wp_tip/overflow.0.session_qualif/script/lemma_j_incr_char.json
+++ b/src/plugins/wp/tests/wp_tip/overflow.0.session_qualif/script/lemma_j_incr_char.json
@@ -1,27 +1,28 @@
-[ { "header": "Overflow", "tactic": "Wp.overflow", "params": {},
+[ { "prover": "script", "verdict": "valid", "time": 0.0322 },
+  { "header": "Overflow", "tactic": "Wp.overflow", "params": {},
     "select": { "select": "inside-goal", "occur": 0,
                 "target": "(to_uint32 c_0)", "pattern": "to_uint32$c" },
-    "children": { "In-Range": [ { "prover": "Alt-Ergo:2.2.0",
-                                  "verdict": "valid", "time": 0.0094,
-                                  "steps": 25 } ],
-                  "Lower": [ { "prover": "Alt-Ergo:2.2.0",
-                               "verdict": "valid", "time": 0.0157,
-                               "steps": 53 },
+    "children": { "In-Range": [ { "prover": "Alt-Ergo:2.4.2",
+                                  "verdict": "valid", "time": 0.0082,
+                                  "steps": 32 } ],
+                  "Lower": [ { "prover": "Alt-Ergo:2.4.2",
+                               "verdict": "valid", "time": 0.024,
+                               "steps": 155 },
                              { "header": "Overflow", "tactic": "Wp.overflow",
                                "params": {},
                                "select": { "select": "inside-goal",
                                            "occur": 0,
                                            "target": "(to_uint32\n  (ui_0+((4294967296+c_0+(-4294967296*(c_0 div 4294967296))) mod 4294967296)))",
                                            "pattern": "to_uint32+$ui%+42949672964294967296" },
-                               "children": { "In-Range": [ { "prover": "Alt-Ergo:2.2.0",
+                               "children": { "In-Range": [ { "prover": "Alt-Ergo:2.4.2",
                                                              "verdict": "valid",
                                                              "time": 0.0166,
                                                              "steps": 27 } ],
-                                             "Lower": [ { "prover": "Alt-Ergo:2.2.0",
+                                             "Lower": [ { "prover": "Alt-Ergo:2.4.2",
                                                           "verdict": "valid",
                                                           "time": 0.023,
                                                           "steps": 25 } ],
-                                             "Upper": [ { "prover": "Alt-Ergo:2.2.0",
+                                             "Upper": [ { "prover": "Alt-Ergo:2.4.2",
                                                           "verdict": "valid",
                                                           "time": 0.0739,
                                                           "steps": 73 } ] } } ],
diff --git a/src/plugins/wp/tests/wp_tip/overflow.0.session_qualif/script/lemma_j_incr_short.json b/src/plugins/wp/tests/wp_tip/overflow.0.session_qualif/script/lemma_j_incr_short.json
index 97c383396b0c68dc8ea302b5db23e1fe35c93227..4e30c1ba53e77f51474cc2b14f03f2bde9d19c1a 100644
--- a/src/plugins/wp/tests/wp_tip/overflow.0.session_qualif/script/lemma_j_incr_short.json
+++ b/src/plugins/wp/tests/wp_tip/overflow.0.session_qualif/script/lemma_j_incr_short.json
@@ -1,27 +1,28 @@
-[ { "header": "Overflow", "tactic": "Wp.overflow", "params": {},
+[ { "prover": "script", "verdict": "valid", "time": 0.0235 },
+  { "header": "Overflow", "tactic": "Wp.overflow", "params": {},
     "select": { "select": "inside-goal", "occur": 0,
                 "target": "(to_uint32 s_0)", "pattern": "to_uint32$s" },
-    "children": { "In-Range": [ { "prover": "Alt-Ergo:2.2.0",
-                                  "verdict": "valid", "time": 0.0098,
-                                  "steps": 25 } ],
-                  "Lower": [ { "prover": "Alt-Ergo:2.2.0",
-                               "verdict": "valid", "time": 0.0198,
-                               "steps": 54 },
+    "children": { "In-Range": [ { "prover": "Alt-Ergo:2.4.2",
+                                  "verdict": "valid", "time": 0.0069,
+                                  "steps": 32 } ],
+                  "Lower": [ { "prover": "Alt-Ergo:2.4.2",
+                               "verdict": "valid", "time": 0.0166,
+                               "steps": 154 },
                              { "header": "Overflow", "tactic": "Wp.overflow",
                                "params": {},
                                "select": { "select": "inside-goal",
                                            "occur": 0,
                                            "target": "(to_uint32\n  (ui_0+((4294967296+s_0+(-4294967296*(s_0 div 4294967296))) mod 4294967296)))",
                                            "pattern": "to_uint32+$ui%+42949672964294967296" },
-                               "children": { "In-Range": [ { "prover": "Alt-Ergo:2.2.0",
+                               "children": { "In-Range": [ { "prover": "Alt-Ergo:2.4.2",
                                                              "verdict": "valid",
                                                              "time": 0.017,
                                                              "steps": 27 } ],
-                                             "Lower": [ { "prover": "Alt-Ergo:2.2.0",
+                                             "Lower": [ { "prover": "Alt-Ergo:2.4.2",
                                                           "verdict": "valid",
                                                           "time": 0.0232,
                                                           "steps": 25 } ],
-                                             "Upper": [ { "prover": "Alt-Ergo:2.2.0",
+                                             "Upper": [ { "prover": "Alt-Ergo:2.4.2",
                                                           "verdict": "valid",
                                                           "time": 0.2614,
                                                           "steps": 73 } ] } } ],
diff --git a/src/plugins/wp/tests/wp_tip/proof.i b/src/plugins/wp/tests/wp_tip/proof.i
new file mode 100644
index 0000000000000000000000000000000000000000..83b6f05d2aaae1a387ffdb8a9d128ca173efc6f7
--- /dev/null
+++ b/src/plugins/wp/tests/wp_tip/proof.i
@@ -0,0 +1,16 @@
+/* run.config
+   DONTRUN:
+*/
+
+/* run.config_qualif
+   OPT: -print
+ */
+
+// Provers
+
+/*@
+  strategy P1: \prover("alt-ergo");
+  strategy P2: \prover(0.5);
+  strategy P3: \prover("alt-ergo",3.0);
+  strategy P4: P1, P2, P3, \default;
+ */
diff --git a/src/plugins/wp/tests/wp_tip/strategy.c b/src/plugins/wp/tests/wp_tip/strategy.c
new file mode 100644
index 0000000000000000000000000000000000000000..48535ecd7a7de5894e172116d7ef8b29294dc5b5
--- /dev/null
+++ b/src/plugins/wp/tests/wp_tip/strategy.c
@@ -0,0 +1,52 @@
+/* run.config
+   DONTRUN:
+*/
+
+/* run.config_qualif
+   OPT: -wp-status -wp-prover tip -wp-script dry -wp-strategy Prover
+   OPT: -wp-status -wp-prover tip -wp-script dry -wp-strategy Eager
+   OPT: -wp-status -wp-prover tip -wp-script dry -wp-strategy EagerRange
+   OPT: -wp-status -wp-prover tip -wp-script dry -wp-strategy Lazy
+ */
+
+/*@
+  axiomatic Observers {
+  predicate P(integer x);
+  }
+*/
+
+/*@
+  strategy Prover: \prover("alt-ergo",0.1);
+
+  strategy Lazy:
+    Prover,
+    \tactic("Wp.overflow"
+      ,\pattern(\any(to_uint32(_),to_sint32(_)))
+    );
+
+  strategy Eager:
+    \tactic("Wp.overflow"
+      ,\pattern(\any(to_uint32(_),to_sint32(_)))
+    ),
+    Prover;
+
+  strategy EagerRange:
+    \tactic("Wp.overflow"
+      ,\pattern(\any(to_uint32(_),to_sint32(_)))
+      ,\child("In-Range",EagerRange)
+      ,\children(Prover)
+    ),
+    Prover;
+
+*/
+
+
+/*@
+  requires x < 1000 && y < 1000 && z < 1000 && t < 1000;
+  ensures P(\result);
+  assigns \nothing;
+*/
+int target(unsigned x, unsigned y, unsigned z, unsigned t)
+{
+  return x+y+z+t;
+}
diff --git a/src/plugins/wp/tests/wp_tip/tac_split_quantifiers.0.session_qualif/script/split_ensures_Goal_Exist_Or.json b/src/plugins/wp/tests/wp_tip/tac_split_quantifiers.0.session_qualif/script/split_ensures_Goal_Exist_Or.json
index c70dddec42c798d67d2e64caedcd77123e5f7e9c..4808c8f42b02e081c60a6b774215a29326d459c5 100644
--- a/src/plugins/wp/tests/wp_tip/tac_split_quantifiers.0.session_qualif/script/split_ensures_Goal_Exist_Or.json
+++ b/src/plugins/wp/tests/wp_tip/tac_split_quantifiers.0.session_qualif/script/split_ensures_Goal_Exist_Or.json
@@ -2,5 +2,4 @@
     "select": { "select": "clause-goal",
                 "target": "exists i_0,i_1,i_2:int.\n(P_Q1 1) \\/ (P_P1 i_0) \\/ (P_P2 i_1 i_2) \\/ (exists i_3:int.\n                                             (P_Q2 i_0 i_3))",
                 "pattern": "\\EP_Q11" },
-    "children": { "Split": [ { "prover": "Alt-Ergo:2.2.0",
-                               "verdict": "unknown" } ] } } ]
+    "children": { "Split": [ ] } } ]
diff --git a/src/plugins/wp/tests/wp_typed/oracle/cast_fits.0.res.oracle b/src/plugins/wp/tests/wp_typed/oracle/cast_fits.0.res.oracle
index 91d993407e90198cfac7642dd37c622a3ba79925..11203eb0f175287b1e86ce888cc404cc9f9c9aa5 100644
--- a/src/plugins/wp/tests/wp_typed/oracle/cast_fits.0.res.oracle
+++ b/src/plugins/wp/tests/wp_typed/oracle/cast_fits.0.res.oracle
@@ -5,9 +5,18 @@
 [wp] cast_fits.i:13: Warning: 
   Cast with incompatible pointers types (source: __anonstruct_L2_2*)
      (target: sint32*)
+[wp:union] cast_fits.i:45: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
+[wp:union] cast_fits.i:52: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
 [wp] cast_fits.i:54: Warning: 
   Cast with incompatible pointers types (source: __anonunion_L8_8*)
      (target: sint32*)
+[wp:union] cast_fits.i:61: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
 [wp] cast_fits.i:60: Warning: 
   Cast with incompatible pointers types (source: sint32*)
      (target: __anonunion_L8_8*)
diff --git a/src/plugins/wp/tests/wp_typed/oracle/cast_fits.1.res.oracle b/src/plugins/wp/tests/wp_typed/oracle/cast_fits.1.res.oracle
index 76f3b9532f3c8ba5cf43aac5657b1af1bfd9d1c9..1d8b88a4d13589c516d004147b4678d62f2ea2ba 100644
--- a/src/plugins/wp/tests/wp_typed/oracle/cast_fits.1.res.oracle
+++ b/src/plugins/wp/tests/wp_typed/oracle/cast_fits.1.res.oracle
@@ -5,9 +5,18 @@
 [wp] cast_fits.i:13: Warning: 
   Cast with incompatible pointers types (source: __anonstruct_L2_2*)
      (target: sint32*)
+[wp:union] cast_fits.i:45: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
+[wp:union] cast_fits.i:52: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
 [wp] cast_fits.i:54: Warning: 
   Cast with incompatible pointers types (source: __anonunion_L8_8*)
      (target: sint32*)
+[wp:union] cast_fits.i:61: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
 [wp] cast_fits.i:60: Warning: 
   Cast with incompatible pointers types (source: sint32*)
      (target: __anonunion_L8_8*)
diff --git a/src/plugins/wp/tests/wp_typed/oracle_qualif/cast_fits.res.oracle b/src/plugins/wp/tests/wp_typed/oracle_qualif/cast_fits.res.oracle
index 8f652bcc9d04f6adee76d97b60152802f2958b57..87ff7ce151b9fecfb0a2e46a31f66fea5b317107 100644
--- a/src/plugins/wp/tests/wp_typed/oracle_qualif/cast_fits.res.oracle
+++ b/src/plugins/wp/tests/wp_typed/oracle_qualif/cast_fits.res.oracle
@@ -5,9 +5,18 @@
 [wp] cast_fits.i:13: Warning: 
   Cast with incompatible pointers types (source: __anonstruct_L2_2*)
      (target: sint32*)
+[wp:union] cast_fits.i:45: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
+[wp:union] cast_fits.i:52: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
 [wp] cast_fits.i:54: Warning: 
   Cast with incompatible pointers types (source: __anonunion_L8_8*)
      (target: sint32*)
+[wp:union] cast_fits.i:61: Warning: 
+  Accessing union fields with WP might be unsound.
+  Please refer to WP manual.
 [wp] cast_fits.i:60: Warning: 
   Cast with incompatible pointers types (source: sint32*)
      (target: __anonunion_L8_8*)
diff --git a/src/plugins/wp/tests/wp_typed/oracle_qualif/frame.res.oracle b/src/plugins/wp/tests/wp_typed/oracle_qualif/frame.res.oracle
index d45965e41d3734ccdf206c083cb67f0dac3fb562..bfa547fec04c79c4e902f386ba93ad7591e83747 100644
--- a/src/plugins/wp/tests/wp_typed/oracle_qualif/frame.res.oracle
+++ b/src/plugins/wp/tests/wp_typed/oracle_qualif/frame.res.oracle
@@ -3,18 +3,18 @@
 [wp] Running WP plugin...
 [wp] Warning: Missing RTE guards
 [wp] 6 goals scheduled
-[wp] [Unsuccess] typed_compound_assert_SEP (Alt-Ergo) (Cached)
+[wp] [Valid] typed_compound_assert_SEP (Alt-Ergo) (Cached)
 [wp] [Valid] typed_compound_assert_RES (Alt-Ergo) (Cached)
 [wp] [Valid] typed_local_region_assert_A_X (Alt-Ergo) (Cached)
 [wp] [Unsuccess] typed_local_region_assert_A_Y (Alt-Ergo) (Cached)
 [wp] [Valid] typed_formal_region_assert_A_X (Alt-Ergo) (Cached)
 [wp] [Unsuccess] typed_formal_region_assert_A_Y (Alt-Ergo) (Cached)
-[wp] Proved goals:    3 / 6
-  Alt-Ergo:        3
-  Unsuccess:       3
+[wp] Proved goals:    4 / 6
+  Alt-Ergo:        4
+  Unsuccess:       2
 ------------------------------------------------------------
  Functions                 WP     Alt-Ergo  Total   Success
-  compound                  -        1        2      50.0%
+  compound                  -        2        2       100%
   local_region              -        1        2      50.0%
   formal_region             -        1        2      50.0%
 ------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.1.res.oracle b/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.1.res.oracle
index 8a24f1e423a4276d97d597a9ac1c3e7203a76bc6..76c6bfc124616648c6b1276948108368101252ff 100644
--- a/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.1.res.oracle
+++ b/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.1.res.oracle
@@ -4,163 +4,559 @@
 [wp] Warning: Missing RTE guards
 [wp] 23 goals scheduled
 [wp] [Valid] typed_init_t2_v2_loop_assigns_part1 (Qed)
-[wp] [Valid] typed_init_t2_v2_loop_assigns_part2 (Tactic) (Alt-Ergo 2/2) (Cached)
-[wp] [Valid] typed_init_t2_v2_loop_assigns_part3 (Tactic) (Alt-Ergo 2/2) (Cached)
+[wp] [Valid] typed_init_t2_v2_loop_assigns_part2 (Tactics 2) (Qed 12/13) (Alt-Ergo 1/13) (Cached)
+[wp] [Valid] typed_init_t2_v2_loop_assigns_part3 (Tactics 2) (Qed 12/13) (Alt-Ergo 1/13) (Cached)
 [wp] [Valid] typed_init_t2_v2_loop_assigns_2_part1 (Qed)
-[wp] [Valid] typed_init_t2_v2_loop_assigns_2_part2 (Tactic) (Alt-Ergo 2/2) (Cached)
-[wp] [Valid] typed_init_t2_v2_loop_assigns_2_part3 (Tactic) (Alt-Ergo 2/2) (Cached)
+[wp] [Valid] typed_init_t2_v2_loop_assigns_2_part2 (Tactics 2) (Qed 12/13) (Alt-Ergo 1/13) (Cached)
+[wp] [Valid] typed_init_t2_v2_loop_assigns_2_part3 (Tactics 3) (Qed 34/34)
 [wp] [Valid] typed_init_t2_v2_assigns_part1 (Qed)
 [wp] [Valid] typed_init_t2_v2_assigns_part2 (Tactic) (Alt-Ergo 2/2) (Cached)
 [wp] [Valid] typed_init_t2_v3_loop_assigns_part1 (Qed)
-[wp] [Valid] typed_init_t2_v3_loop_assigns_part2 (Tactic) (Alt-Ergo 2/2) (Cached)
-[wp] [Valid] typed_init_t2_v3_loop_assigns_part3 (Tactic) (Alt-Ergo 2/2) (Cached)
+[wp] [Valid] typed_init_t2_v3_loop_assigns_part2 (Tactics 2) (Qed 12/13) (Alt-Ergo 1/13) (Cached)
+[wp] [Valid] typed_init_t2_v3_loop_assigns_part3 (Tactics 3) (Qed 34/34)
 [wp] [Valid] typed_init_t2_v3_loop_assigns_2_part1 (Qed)
 [wp] [Valid] typed_init_t2_v3_loop_assigns_2_part2 (Qed)
 [wp] [Valid] typed_init_t2_v3_assigns_part1 (Qed)
 [wp] [Valid] typed_init_t2_v3_assigns_part2 (Tactic) (Alt-Ergo 2/2) (Cached)
 [wp] [Valid] typed_init_t2_bis_v2_loop_assigns_part1 (Qed)
-[wp] [Valid] typed_init_t2_bis_v2_loop_assigns_part2 (Tactic) (Alt-Ergo 2/2) (Cached)
-[wp] [Valid] typed_init_t2_bis_v2_loop_assigns_part3 (Tactic) (Alt-Ergo 2/2) (Cached)
+[wp] [Valid] typed_init_t2_bis_v2_loop_assigns_part2 (Tactics 2) (Qed 12/13) (Alt-Ergo 1/13) (Cached)
+[wp] [Valid] typed_init_t2_bis_v2_loop_assigns_part3 (Tactics 2) (Qed 22/23) (Alt-Ergo 1/23) (Cached)
 [wp] [Valid] typed_init_t2_bis_v2_assigns_exit_part1 (Qed)
-[wp] [Valid] typed_init_t2_bis_v2_assigns_exit_part2 (Tactic) (Alt-Ergo 2/2) (Cached)
+[wp] [Valid] typed_init_t2_bis_v2_assigns_exit_part2 (Tactics 2) (Qed 12/13) (Alt-Ergo 1/13) (Cached)
 [wp] [Valid] typed_init_t2_bis_v2_assigns_exit_part3 (Qed)
 [wp] [Valid] typed_init_t2_bis_v2_assigns_normal_part1 (Qed)
-[wp] [Valid] typed_init_t2_bis_v2_assigns_normal_part2 (Tactic) (Alt-Ergo 2/2) (Cached)
+[wp] [Valid] typed_init_t2_bis_v2_assigns_normal_part2 (Tactics 2) (Qed 12/13) (Alt-Ergo 1/13) (Cached)
 [wp] Proved goals:   23 / 23
   Qed:            11
-  Script:         12 (Tactics 12) (Alt-Ergo 24/24) (Cached)
+  Script:         12 (Tactics 24) (Qed 174/186) (Alt-Ergo 12/186) (Cached)
 [wp] Proof script for typed_init_t2_bis_v2_assigns_normal_part2:
   [ { "header": "Split", "tactic": "Wp.split", "params": {},
       "select": { "select": "clause-goal",
                   "target": "exists i_0,i_1:int.\n(i_0<=i_138) /\\ (i_1<=i_139) /\\ (0<=i_0) /\\ (i_138<=i_0) /\\ (i_139<=i_1)\n/\\ (i_0<=9)",
                   "pattern": "\\E$i$i0$i$i9" },
-      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0088,
-                                    "steps": 24 } ],
-                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0116,
-                                    "steps": 24 } ] } } ]
+      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "valid", "time": 0.3801,
+                                    "steps": 1028 } ],
+                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "timeout", "time": 10. },
+                                  { "header": "Range", "tactic": "Wp.range",
+                                    "params": { "inf": 0, "sup": 9 },
+                                    "select": { "select": "inside-goal",
+                                                "occur": 0, "target": "i_138",
+                                                "pattern": "$i" },
+                                    "children": { "Lower 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 1": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 2": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 3": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 4": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 5": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 6": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 7": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 8": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Upper 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ] } } ] } } ]
 [wp] Proof script for typed_init_t2_bis_v2_assigns_exit_part2:
   [ { "header": "Split", "tactic": "Wp.split", "params": {},
       "select": { "select": "clause-goal",
                   "target": "exists i_0,i_1:int.\n(i_0<=i_138) /\\ (i_1<=i_139) /\\ (0<=i_0) /\\ (i_138<=i_0) /\\ (i_139<=i_1)\n/\\ (i_0<=9)",
                   "pattern": "\\E$i$i0$i$i9" },
-      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0088,
-                                    "steps": 24 } ],
-                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0116,
-                                    "steps": 24 } ] } } ]
+      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "valid", "time": 0.3801,
+                                    "steps": 1028 } ],
+                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "timeout", "time": 10. },
+                                  { "header": "Range", "tactic": "Wp.range",
+                                    "params": { "inf": 0, "sup": 9 },
+                                    "select": { "select": "inside-goal",
+                                                "occur": 0, "target": "i_138",
+                                                "pattern": "$i" },
+                                    "children": { "Lower 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 1": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 2": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 3": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 4": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 5": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 6": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 7": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 8": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Upper 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ] } } ] } } ]
 [wp] Proof script for typed_init_t2_bis_v2_loop_assigns_part3:
   [ { "header": "Split", "tactic": "Wp.split", "params": {},
       "select": { "select": "clause-goal",
                   "target": "exists i_0,i_2:int.\n(i_0<=i_1) /\\ (i_2<=i_3) /\\ (0<=i_0) /\\ (i_1<=i_0) /\\ (i_3<=i_2) /\\ (i_0<=9)",
                   "pattern": "\\E$i$i0$i$i9" },
-      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0074,
-                                    "steps": 31 } ],
-                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0078,
-                                    "steps": 31 } ] } } ]
+      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "timeout", "time": 10. },
+                                  { "header": "Range", "tactic": "Wp.range",
+                                    "params": { "inf": 0, "sup": 19 },
+                                    "select": { "select": "inside-goal",
+                                                "occur": 0, "target": "i_3",
+                                                "pattern": "$i" },
+                                    "children": { "Lower 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 1": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 2": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 3": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 4": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 5": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 6": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 7": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 8": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 10": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 11": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 12": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 13": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 14": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 15": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 16": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 17": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 18": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 19": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Upper 19": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ] } } ],
+                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "valid", "time": 7.1853,
+                                    "steps": 25331 } ] } } ]
 [wp] Proof script for typed_init_t2_bis_v2_loop_assigns_part2:
   [ { "header": "Split", "tactic": "Wp.split", "params": {},
       "select": { "select": "clause-goal",
                   "target": "exists i_0,i_1:int.\n(i_0<=i_9) /\\ (i_1<=i_10) /\\ (0<=i_0) /\\ (i_9<=i_0) /\\ (i_10<=i_1)\n/\\ (i_0<=9)",
                   "pattern": "\\E$i$i0$i$i9" },
-      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0124,
-                                    "steps": 43 } ],
-                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0121,
-                                    "steps": 43 } ] } } ]
+      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "valid", "time": 7.5676,
+                                    "steps": 26376 } ],
+                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "timeout", "time": 10. },
+                                  { "header": "Range", "tactic": "Wp.range",
+                                    "params": { "inf": 0, "sup": 9 },
+                                    "select": { "select": "inside-goal",
+                                                "occur": 0, "target": "i_9",
+                                                "pattern": "$i" },
+                                    "children": { "Lower 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 1": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 2": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 3": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 4": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 5": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 6": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 7": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 8": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Upper 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ] } } ] } } ]
 [wp] Proof script for typed_init_t2_v3_assigns_part2:
   [ { "header": "Split", "tactic": "Wp.split", "params": {},
       "select": { "select": "clause-goal",
                   "target": "exists i_0,i_1:int.\n(i_0<=i_149) /\\ (i_1<=i_150) /\\ (0<=i_0) /\\ (i_149<=i_0) /\\ (i_150<=i_1)\n/\\ (i_0<=9)",
                   "pattern": "\\E$i$i0$i$i9" },
-      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.011,
-                                    "steps": 16 } ],
-                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0092,
-                                    "steps": 16 } ] } } ]
+      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "valid", "time": 0.0835,
+                                    "steps": 193 } ],
+                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "valid", "time": 1.8111,
+                                    "steps": 5702 } ] } } ]
 [wp] Proof script for typed_init_t2_v3_loop_assigns_part3:
   [ { "header": "Split", "tactic": "Wp.split", "params": {},
       "select": { "select": "clause-goal",
                   "target": "exists i_0,i_1:int.\n(i_0<=i_4) /\\ (i_1<=i_6) /\\ (0<=i_0) /\\ (i_4<=i_0) /\\ (i_6<=i_1) /\\ (i_0<=9)",
                   "pattern": "\\E$i$i0$i$i9" },
-      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0169,
-                                    "steps": 33 } ],
-                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0081,
-                                    "steps": 33 } ] } } ]
+      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "timeout", "time": 10. },
+                                  { "header": "Range", "tactic": "Wp.range",
+                                    "params": { "inf": 0, "sup": 19 },
+                                    "select": { "select": "inside-goal",
+                                                "occur": 0, "target": "i_6",
+                                                "pattern": "$i" },
+                                    "children": { "Lower 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 1": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 2": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 3": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 4": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 5": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 6": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 7": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 8": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 10": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 11": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 12": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 13": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 14": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 15": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 16": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 17": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 18": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 19": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Upper 19": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ] } } ],
+                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "timeout", "time": 10. },
+                                  { "header": "Range", "tactic": "Wp.range",
+                                    "params": { "inf": 0, "sup": 9 },
+                                    "select": { "select": "inside-goal",
+                                                "occur": 0, "target": "i_4",
+                                                "pattern": "$i" },
+                                    "children": { "Lower 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 1": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 2": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 3": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 4": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 5": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 6": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 7": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 8": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Upper 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ] } } ] } } ]
 [wp] Proof script for typed_init_t2_v3_loop_assigns_part2:
   [ { "header": "Split", "tactic": "Wp.split", "params": {},
       "select": { "select": "clause-goal",
                   "target": "exists i_0,i_1:int.\n(i_0<=i_13) /\\ (i_1<=i_14) /\\ (0<=i_0) /\\ (i_13<=i_0) /\\ (i_14<=i_1)\n/\\ (i_0<=9)",
                   "pattern": "\\E$i$i0$i$i9" },
-      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0139,
-                                    "steps": 45 } ],
-                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0127,
-                                    "steps": 45 } ] } } ]
+      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "valid", "time": 1.3179,
+                                    "steps": 3085 } ],
+                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "timeout", "time": 10. },
+                                  { "header": "Range", "tactic": "Wp.range",
+                                    "params": { "inf": 0, "sup": 9 },
+                                    "select": { "select": "inside-goal",
+                                                "occur": 0, "target": "i_13",
+                                                "pattern": "$i" },
+                                    "children": { "Lower 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 1": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 2": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 3": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 4": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 5": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 6": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 7": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 8": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Upper 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ] } } ] } } ]
 [wp] Proof script for typed_init_t2_v2_assigns_part2:
   [ { "header": "Split", "tactic": "Wp.split", "params": {},
       "select": { "select": "clause-goal",
                   "target": "exists i_0,i_1:int.\n(i_0<=i_158) /\\ (i_1<=i_159) /\\ (0<=i_0) /\\ (i_158<=i_0) /\\ (i_159<=i_1)\n/\\ (i_0<=9)",
                   "pattern": "\\E$i$i0$i$i9" },
-      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.011,
-                                    "steps": 16 } ],
-                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0092,
-                                    "steps": 16 } ] } } ]
+      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "valid", "time": 0.0835,
+                                    "steps": 193 } ],
+                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "valid", "time": 1.8111,
+                                    "steps": 5702 } ] } } ]
 [wp] Proof script for typed_init_t2_v2_loop_assigns_2_part3:
   [ { "header": "Split", "tactic": "Wp.split", "params": {},
       "select": { "select": "clause-goal",
                   "target": "exists i_0,i_2:int.\n(i_0<=i_1) /\\ (0<=i_0) /\\ (i_1<=i_0) /\\ (j_1<=i_2) /\\ (i_2<=j_1) /\\ (i_0<=9)",
                   "pattern": "\\E$i0$i$j$j9" },
-      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0094,
-                                    "steps": 26 } ],
-                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0101,
-                                    "steps": 26 } ] } } ]
+      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "timeout", "time": 10. },
+                                  { "header": "Range", "tactic": "Wp.range",
+                                    "params": { "inf": 0, "sup": 19 },
+                                    "select": { "select": "inside-goal",
+                                                "occur": 0, "target": "j_1",
+                                                "pattern": "$j" },
+                                    "children": { "Lower 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 1": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 2": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 3": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 4": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 5": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 6": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 7": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 8": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 10": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 11": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 12": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 13": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 14": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 15": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 16": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 17": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 18": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Value 19": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ],
+                                                  "Upper 19": [ { "prover": "qed",
+                                                                  "verdict": "valid" } ] } } ],
+                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "timeout", "time": 10. },
+                                  { "header": "Range", "tactic": "Wp.range",
+                                    "params": { "inf": 0, "sup": 9 },
+                                    "select": { "select": "inside-goal",
+                                                "occur": 0, "target": "i_1",
+                                                "pattern": "$i" },
+                                    "children": { "Lower 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 1": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 2": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 3": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 4": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 5": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 6": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 7": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 8": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Upper 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ] } } ] } } ]
 [wp] Proof script for typed_init_t2_v2_loop_assigns_2_part2:
   [ { "header": "Split", "tactic": "Wp.split", "params": {},
       "select": { "select": "clause-goal",
                   "target": "exists i_0,i_1:int.\n(i_0<=i_13) /\\ (i_1<=i_14) /\\ (0<=i_0) /\\ (i_13<=i_0) /\\ (i_14<=i_1)\n/\\ (i_0<=9)",
                   "pattern": "\\E$i$i0$i$i9" },
-      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0099,
-                                    "steps": 42 } ],
-                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0124,
-                                    "steps": 42 } ] } } ]
+      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "valid", "time": 1.9461,
+                                    "steps": 3681 } ],
+                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "timeout", "time": 10. },
+                                  { "header": "Range", "tactic": "Wp.range",
+                                    "params": { "inf": 0, "sup": 9 },
+                                    "select": { "select": "inside-goal",
+                                                "occur": 0, "target": "i_13",
+                                                "pattern": "$i" },
+                                    "children": { "Lower 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 1": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 2": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 3": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 4": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 5": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 6": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 7": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 8": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Upper 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ] } } ] } } ]
 [wp] Proof script for typed_init_t2_v2_loop_assigns_part3:
   [ { "header": "Split", "tactic": "Wp.split", "params": {},
       "select": { "select": "clause-goal",
                   "target": "exists i_0,i_1:int.\n(i_0<=i_8) /\\ (i_1<=i_9) /\\ (0<=i_0) /\\ (i_8<=i_0) /\\ (i_9<=i_1) /\\ (i_0<=9)",
                   "pattern": "\\E$i$i0$i$i9" },
-      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0098,
-                                    "steps": 35 } ],
-                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0048,
-                                    "steps": 35 } ] } } ]
+      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "valid", "time": 1.2688,
+                                    "steps": 2727 } ],
+                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "timeout", "time": 10. },
+                                  { "header": "Range", "tactic": "Wp.range",
+                                    "params": { "inf": 0, "sup": 9 },
+                                    "select": { "select": "inside-goal",
+                                                "occur": 0, "target": "i_8",
+                                                "pattern": "$i" },
+                                    "children": { "Lower 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 1": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 2": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 3": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 4": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 5": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 6": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 7": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 8": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Upper 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ] } } ] } } ]
 [wp] Proof script for typed_init_t2_v2_loop_assigns_part2:
   [ { "header": "Split", "tactic": "Wp.split", "params": {},
       "select": { "select": "clause-goal",
                   "target": "exists i_0,i_1:int.\n(i_0<=i_21) /\\ (i_1<=i_22) /\\ (0<=i_0) /\\ (i_21<=i_0) /\\ (i_22<=i_1)\n/\\ (i_0<=9)",
                   "pattern": "\\E$i$i0$i$i9" },
-      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0098,
-                                    "steps": 35 } ],
-                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0",
-                                    "verdict": "valid", "time": 0.0048,
-                                    "steps": 35 } ] } } ]
+      "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "valid", "time": 1.2688,
+                                    "steps": 2727 } ],
+                    "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2",
+                                    "verdict": "timeout", "time": 10. },
+                                  { "header": "Range", "tactic": "Wp.range",
+                                    "params": { "inf": 0, "sup": 9 },
+                                    "select": { "select": "inside-goal",
+                                                "occur": 0, "target": "i_21",
+                                                "pattern": "$i" },
+                                    "children": { "Lower 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 0": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 1": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 2": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 3": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 4": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 5": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 6": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 7": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 8": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Value 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ],
+                                                  "Upper 9": [ { "prover": "qed",
+                                                                 "verdict": "valid" } ] } } ] } } ]
 [wp] Updated session
    - 12 new valid scripts
 ------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_usage/oracle/switch.0.res.oracle b/src/plugins/wp/tests/wp_usage/oracle/switch.0.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..0d25c225e9b863ac6bc3eddcbc36f2d340d2b695
--- /dev/null
+++ b/src/plugins/wp/tests/wp_usage/oracle/switch.0.res.oracle
@@ -0,0 +1,37 @@
+# frama-c -wp [...]
+[kernel] Parsing switch.i (no preprocessing)
+[kernel] switch.i:10: Warning: 
+  parsing obsolete ACSL construct 'logic declaration'. 'an axiomatic block' should be used instead.
+[wp] Running WP plugin...
+[wp] Warning: Missing RTE guards
+------------------------------------------------------------
+  Function f
+------------------------------------------------------------
+
+Goal Post-condition (file switch.i, line 12) in 'f' (1/3):
+Tags: Default.
+Assume {
+  Type: is_sint32(x).
+  (* Default *)
+  Have: (x != 0) /\ (x != 1) /\ (x != 2) /\ (x != 3).
+}
+Prove: P_P(30).
+
+------------------------------------------------------------
+
+Goal Post-condition (file switch.i, line 12) in 'f' (2/3):
+Tags: Case 3.
+Prove: P_P(20).
+
+------------------------------------------------------------
+
+Goal Post-condition (file switch.i, line 12) in 'f' (3/3):
+Tags: Cases 0,1,2.
+Assume {
+  Type: is_sint32(x).
+  (* Cases 0,1,2 *)
+  Have: (x = 0) \/ (x = 1) \/ (x = 2).
+}
+Prove: P_P(10).
+
+------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_usage/oracle/switch.1.res.oracle b/src/plugins/wp/tests/wp_usage/oracle/switch.1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..05401cb7de08cd90b0fe752ea130d2109f25e1c2
--- /dev/null
+++ b/src/plugins/wp/tests/wp_usage/oracle/switch.1.res.oracle
@@ -0,0 +1,29 @@
+# frama-c -wp [...]
+[kernel] Parsing switch.i (no preprocessing)
+[kernel] switch.i:10: Warning: 
+  parsing obsolete ACSL construct 'logic declaration'. 'an axiomatic block' should be used instead.
+[wp] Running WP plugin...
+[wp] Warning: Missing RTE guards
+------------------------------------------------------------
+  Function f
+------------------------------------------------------------
+
+Goal Post-condition (file switch.i, line 12) in 'f':
+Assume {
+  Type: is_sint32(f) /\ is_sint32(x).
+  (* Merge *)
+  Either {
+    Case:
+      (* Cases 0,1,2 *)
+      Have: (x = 0) \/ (x = 1) \/ (x = 2).
+      Have: f = 10.
+    Case: (* Case 3 *) Have: x = 3. Have: f = 20.
+    Case:
+      (* Default *)
+      Have: (x != 0) /\ (x != 1) /\ (x != 2) /\ (x != 3).
+      Have: f = 30.
+  }
+}
+Prove: P_P(f).
+
+------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_usage/switch.i b/src/plugins/wp/tests/wp_usage/switch.i
new file mode 100644
index 0000000000000000000000000000000000000000..5dd6ae4b6171f91633e793c636099a8582ed25f0
--- /dev/null
+++ b/src/plugins/wp/tests/wp_usage/switch.i
@@ -0,0 +1,24 @@
+/* run.config
+   OPT:
+   OPT: -wp-no-split-switch
+*/
+
+/* run.config_qualif
+   DONTRUN:
+*/
+
+//@ predicate P(integer v);
+
+/*@ ensures P(\result); */
+int f(int x) {
+  switch(x) {
+  case 0:
+  case 1:
+  case 2:
+    return 10;
+  case 3:
+    return 20;
+  default:
+    return 30;
+  }
+}
diff --git a/src/plugins/wp/wp.ml b/src/plugins/wp/wp.ml
index fee701a4e93cb711c41f82ebaba10288d38bcfe2..4b5e2dffbd611dc4f6e0afe23ffb03d873d662b2 100644
--- a/src/plugins/wp/wp.ml
+++ b/src/plugins/wp/wp.ml
@@ -190,6 +190,7 @@ module ProofScript = ProofScript
 module ProverScript = ProverScript
 module ProverSearch = ProverSearch
 module ProofSession = ProofSession
+module ProofStrategy = ProofStrategy
 
 (** {2 Tactics} *)
 
@@ -217,6 +218,7 @@ module TacSequence = TacSequence
 module TacShift = TacShift
 module TacSplit = TacSplit
 module TacUnfold = TacUnfold
+module TacCompute = TacCompute
 
 (** {2 Error Management} *)
 
diff --git a/src/plugins/wp/wpContext.ml b/src/plugins/wp/wpContext.ml
index 1adc3cfd70d17731f5f4d2198cca1b046abaf920..238d6c163ac643dac8ed5d664298ac9d988eb6c0 100644
--- a/src/plugins/wp/wpContext.ml
+++ b/src/plugins/wp/wpContext.ml
@@ -490,10 +490,11 @@ module type Generator =
 sig
   type key
   type data
-  val get : key -> data
   val mem : key -> bool
-  val clear : unit -> unit
+  val get : key -> data
+  val set : key -> data -> unit
   val remove : key -> unit
+  val clear : unit -> unit
 end
 
 module StaticGenerator(K : Key)(D : Data with type key = K.t) =
@@ -508,6 +509,7 @@ struct
   type key = D.key
   type data = D.data
   let get = G.memoize D.compile
+  let set = G.update
   let mem = G.mem
   let clear = G.clear
   let remove = G.remove
@@ -525,6 +527,7 @@ struct
   type key = D.key
   type data = D.data
   let get = G.memoize D.compile
+  let set = G.update
   let mem = G.mem
   let clear = G.clear
   let remove = G.remove
@@ -542,6 +545,7 @@ struct
   type key = D.key
   type data = D.data
   let get = G.memoize (fun k -> D.compile k (G.id ~basename:(D.basename k) k))
+  let set = G.update
   let mem = G.mem
   let clear = G.clear
   let remove = G.remove
@@ -559,6 +563,7 @@ struct
   type key = D.key
   type data = D.data
   let get = G.memoize (fun k -> D.compile k (G.id ~basename:(D.basename k) k))
+  let set = G.update
   let mem = G.mem
   let clear = G.clear
   let remove = G.remove
diff --git a/src/plugins/wp/wpContext.mli b/src/plugins/wp/wpContext.mli
index 17a3273679d240ac7e24c53eb9716cae712378a6..9f6be07073a925679b0ca1e7c1a162a899d9544d 100644
--- a/src/plugins/wp/wpContext.mli
+++ b/src/plugins/wp/wpContext.mli
@@ -112,7 +112,7 @@ sig
   val clear : unit -> unit
   val remove : key -> unit
   val define : key -> data -> unit
-  (** no redefinition ; circularity protected *)
+  (** no redefinition unless forced ; circularity protected *)
 
   val update : key -> data -> unit
   (** set current value, with no protection *)
@@ -163,10 +163,11 @@ module type Generator =
 sig
   type key
   type data
-  val get : key -> data
   val mem : key -> bool
-  val clear : unit -> unit
+  val get : key -> data
+  val set : key -> data -> unit
   val remove : key -> unit
+  val clear : unit -> unit
 end
 
 (** projectified, depend on the model, not serialized *)
diff --git a/src/plugins/wp/wpPropId.ml b/src/plugins/wp/wpPropId.ml
index 1ca08f3e221fdd78b5be9f44997876149eed18e8..3632d8514dd634e86021c748e118798b24219317 100644
--- a/src/plugins/wp/wpPropId.ml
+++ b/src/plugins/wp/wpPropId.ml
@@ -746,7 +746,10 @@ let user_prop_pid pid =
   let p_prop = match pid.p_kind with
     | PKPre (_,_,p_prop) -> p_prop
     | _ -> property_of_id pid in
-  user_prop_names p_prop
+  let names = user_prop_names p_prop in
+  match Property.get_kf p_prop with
+  | None -> names
+  | Some kf -> Kernel_function.get_name kf :: names
 
 let select_default pid =
   let names = user_prop_pid pid in
diff --git a/src/plugins/wp/wpReached.ml b/src/plugins/wp/wpReached.ml
index d797a9f04791cd8b3ef40aad0317cdd56748a260..0193f2e46302df193b6845b86662edd7be889299 100644
--- a/src/plugins/wp/wpReached.ml
+++ b/src/plugins/wp/wpReached.ml
@@ -211,9 +211,9 @@ let rec protected node =
 
 and protected_by prev =
   match prev.flow with
-  | F_dead | F_entry | F_effect -> true
+  | F_return | F_dead | F_entry | F_effect -> true
   | F_goto -> protected prev
-  | F_call | F_branch | F_return -> unreachable prev
+  | F_call | F_branch -> unreachable prev
 
 let smoking_node n =
   match n.flow with
diff --git a/src/plugins/wp/wpTacApi.ml b/src/plugins/wp/wpTacApi.ml
index 97e5c4d33bf2542e555259a6d8e032979549163c..8aec7bffc6a821cfcd523ab067e4bc09417a9c80 100644
--- a/src/plugins/wp/wpTacApi.ml
+++ b/src/plugins/wp/wpTacApi.ml
@@ -402,7 +402,7 @@ class configurator (tactic : Tactical.tactical) =
 
     method private commit tree node process =
       try
-        let jtactic = ProofScript.jtactic ~title tactic target in
+        let jtactic = ProofScript.jtactic tactic target in
         let fork = ProofEngine.fork tree ~anchor:node jtactic process in
         let children = snd @@ ProofEngine.commit fork in
         List.map snd children
diff --git a/src/plugins/wp/wp_parameters.ml b/src/plugins/wp/wp_parameters.ml
index 23ff0dda57c622e47b57170e242faee62c225069..7a37701948b3aed89218fd9b2d1433c3b81b6453 100644
--- a/src/plugins/wp/wp_parameters.ml
+++ b/src/plugins/wp/wp_parameters.ml
@@ -440,30 +440,34 @@ module SmokeDeadloop =
   end)
 
 let () = Parameter_customize.set_group wp_strategy
-module Split =
+module SplitBranch =
   False(struct
     let option_name = "-wp-split"
-    let help = "Split conjunctions into sub-goals."
+    let help = "Split if-then-else into sub-goals (see also -wp-max-split)"
   end)
 
 let () = Parameter_customize.set_group wp_strategy
-module UnfoldAssigns =
-  Int(struct
-    let option_name = "-wp-unfold-assigns"
-    let default = 0
-    let arg_name = "n"
-    let help = "Unfold up to <n> levels of aggregates and arrays in assigns.\n\
-                Value -1 means unlimited depth (default 0)"
+module SplitSwitch =
+  True(struct
+    let option_name = "-wp-split-switch"
+    let help = "Split switch-cases into sub-goals (see also -wp-max-split)."
+  end)
+
+let () = Parameter_customize.set_group wp_strategy
+module SplitConj =
+  False(struct
+    let option_name = "-wp-split-conj"
+    let help = "Split conjunctive goals into sub-goals"
   end)
 
 let () = Parameter_customize.set_group wp_strategy
-module SplitDepth =
+module SplitCNF =
   Int(struct
-    let option_name = "-wp-split-depth"
+    let option_name = "-wp-split-cnf"
     let default = 0
-    let arg_name = "p"
-    let help = "Set depth for splitting conjunctions into sub-goals.\n\
-                Value -1 means unlimited depth (default 0)"
+    let arg_name = "N"
+    let help =
+      "Apply CNF transformation on goals at depth N (default 0, -1 unlimited)"
   end)
 
 let () = Parameter_customize.set_group wp_strategy
@@ -475,6 +479,16 @@ module SplitMax =
     let help = "Set maximum number of splitted sub-goals (default 1000)"
   end)
 
+let () = Parameter_customize.set_group wp_strategy
+module UnfoldAssigns =
+  Int(struct
+    let option_name = "-wp-unfold-assigns"
+    let default = 0
+    let arg_name = "n"
+    let help = "Unfold up to <n> levels of aggregates and arrays in assigns.\n\
+                Value -1 means unlimited depth (default 0)"
+  end)
+
 let () = Parameter_customize.set_group wp_strategy
 let () = Parameter_customize.is_invisible ()
 module DynCall =
@@ -694,13 +708,43 @@ module Interactive = String
       let help =
         "WP mode for interactive Why-3 provers (eg: Coq):\n\
          - 'batch': check current proof (default)\n\
-         - 'update': update and check proof\n\
-         - 'edit': edit proof before check\n\
-         - 'fix': check and edit proof if necessary\n\
-         - 'fixup': update proof and fix\n\
+         - 'update': check updated proof\n\
+         - 'edit': edit current proof\n\
+         - 'fix': check current proof and edit if needed\n\
+         - 'fixup': update proof, check it and edit if needed\n\
         "
     end)
 
+let () = Parameter_customize.set_group wp_prover
+module ScriptMode = String
+    (struct
+      let option_name = "-wp-script"
+      let arg_name = "mode"
+      let default = ""
+      let help =
+        "WP mode for managing scripts and proof strategies:\n\
+         - 'batch': proof scripts are reused but not updated (default for script prover)\n\
+         - 'update': proof scripts are reused and updated (default for tip prover)\n\
+         - 'init': proof scripts are generated from scratch and saved\n\
+         - 'dry': proof scripts are explored from scratch and not saved\n\
+         See also option -wp-cache-env."
+    end)
+
+let () = Parameter_customize.set_group wp_prover
+module StrategyEngine = True
+    (struct
+      let option_name = "-wp-strategy-engine"
+      let help = "Activate @strategy and @proof annotations. (default: yes)"
+    end)
+
+let () = Parameter_customize.set_group wp_prover
+module DefaultStrategies = String_list
+    (struct
+      let option_name = "-wp-strategy"
+      let arg_name = "s,..."
+      let help = "Use the specified strategies as default."
+    end)
+
 let () = Parameter_customize.set_group wp_prover
 module RunAllProvers =
   False(struct
@@ -723,18 +767,7 @@ module Cache = String
          - 'replay': update mode with no cache update\n\
          - 'rebuild': always run provers and update cache\n\
          - 'offline': use cache but never run provers\n\
-         You can also use the environment variable FRAMAC_WP_CACHE instead."
-    end)
-
-let () = Parameter_customize.set_group wp_prover
-module CacheEnv = False
-    (struct
-      let option_name = "-wp-cache-env"
-      let help = "Gives environment variables precedence over command line\n\
-                  for cache management:\n\
-                  - FRAMAC_WP_CACHE overrides -wp-cache\n\
-                  - FRAMAC_WP_CACHEDIR overrides -wp-cache-dir\n\
-                  Disabled by default."
+         See also option -wp-cache-env."
     end)
 
 let () = Parameter_customize.set_group wp_prover
@@ -746,7 +779,19 @@ module CacheDir = String
       let help =
         "Specify global cache directory (no cleanup mode).\n\
          By default, cache entries are stored in the WP session directory.\n\
-         You can also use the environment variable FRAMAC_WP_CACHEDIR instead."
+         See also option -wp-cache-env."
+    end)
+
+let () = Parameter_customize.set_group wp_prover
+module CacheEnv = False
+    (struct
+      let option_name = "-wp-cache-env"
+      let help = "Gives environment variables precedence over command line\n\
+                  for cache management:\n\
+                  - FRAMAC_WP_SCRIPT overrides -wp-script\n\
+                  - FRAMAC_WP_CACHE overrides -wp-cache\n\
+                  - FRAMAC_WP_CACHEDIR overrides -wp-cache-dir\n\
+                  Disabled by default."
     end)
 
 let () = Parameter_customize.set_group wp_prover
@@ -805,6 +850,14 @@ module Detect = Action
     end)
 let () = on_reset Detect.clear
 
+module Tactics = String_list
+    (struct
+      let option_name = "-wp-tactic"
+      let arg_name = "id,..."
+      let help = "Describe tactic. Use '?' for listing tactic names."
+    end)
+let () = on_reset Tactics.clear
+
 let () = Parameter_customize.set_group wp_prover
 module Drivers =
   String_list
@@ -827,7 +880,7 @@ let () = Parameter_customize.set_group wp_prover
 module Timeout =
   Int(struct
     let option_name = "-wp-timeout"
-    let default = 10
+    let default = 2
     let arg_name = "n"
     let help =
       Printf.sprintf
@@ -1022,6 +1075,15 @@ module Print =
   end)
 let () = on_reset Print.clear
 
+let () = Parameter_customize.set_group wp_po
+let () = Parameter_customize.do_not_save ()
+module Status =
+  Action(struct
+    let option_name = "-wp-status"
+    let help = "Pretty-prints pending proof obligations on standard output."
+  end)
+let () = on_reset Print.clear
+
 let () = Parameter_customize.set_group wp_po
 let () = Parameter_customize.do_not_save ()
 module Report =
diff --git a/src/plugins/wp/wp_parameters.mli b/src/plugins/wp/wp_parameters.mli
index 786bf2d170668267ba39a507a078806ac18793de..53d15e5b02311f7fd22328e247729ded1359ba4b 100644
--- a/src/plugins/wp/wp_parameters.mli
+++ b/src/plugins/wp/wp_parameters.mli
@@ -92,9 +92,11 @@ module Ground: Parameter_sig.Bool
 module Reduce: Parameter_sig.Bool
 module ExtEqual : Parameter_sig.Bool
 module UnfoldAssigns : Parameter_sig.Int
-module Split: Parameter_sig.Bool
+module SplitBranch: Parameter_sig.Bool
+module SplitSwitch: Parameter_sig.Bool
 module SplitMax: Parameter_sig.Int
-module SplitDepth: Parameter_sig.Int
+module SplitConj: Parameter_sig.Bool
+module SplitCNF: Parameter_sig.Int
 module DynCall : Parameter_sig.Bool
 module SimplifyIsCint : Parameter_sig.Bool
 module SimplifyLandMask : Parameter_sig.Bool
@@ -110,6 +112,7 @@ module TerminatesVariantHyp : Parameter_sig.Bool
 (** {2 Prover Interface} *)
 
 module Detect: Parameter_sig.Bool
+module Tactics: Parameter_sig.String_list
 module Generate:Parameter_sig.Bool
 module ScriptOnStdout: Parameter_sig.Bool
 module PrepareScripts: Parameter_sig.Bool
@@ -117,6 +120,9 @@ module FinalizeScripts: Parameter_sig.Bool
 module DryFinalizeScripts: Parameter_sig.Bool
 module Provers: Parameter_sig.String_list
 module Interactive: Parameter_sig.String
+module StrategyEngine: Parameter_sig.Bool
+module ScriptMode: Parameter_sig.String
+module DefaultStrategies: Parameter_sig.String_list
 module RunAllProvers: Parameter_sig.Bool
 module Cache: Parameter_sig.String
 module CacheEnv: Parameter_sig.Bool
@@ -147,6 +153,7 @@ module BackTrack: Parameter_sig.Int
 
 module TruncPropIdFileName: Parameter_sig.Int
 module Print: Parameter_sig.Bool
+module Status: Parameter_sig.Bool
 module Report: Parameter_sig.String_list
 module ReportJson: Parameter_sig.String
 module OldReportJson: Parameter_sig.String
diff --git a/src/plugins/wp/wpo.ml b/src/plugins/wp/wpo.ml
index e318b87601001b8bd67417fdfde5264bedee2177..f8e1321feabd05400a7f3e2702e21c512798a50e 100644
--- a/src/plugins/wp/wpo.ml
+++ b/src/plugins/wp/wpo.ml
@@ -886,6 +886,10 @@ let pp_goal_model fmt w =
 
 let pp_goal fmt w = WpContext.on_context (get_context w) (pp_goal_model fmt) w
 
+let pp_flow fmt =
+  Format.fprintf fmt "@\n%s@\n" bar ;
+  flow := false
+
 let pp_goal_flow fmt g =
   begin
     if not !flow then Format.pp_print_newline fmt () ;
diff --git a/src/plugins/wp/wpo.mli b/src/plugins/wp/wpo.mli
index 7d62470252ee947250b1cc6eadb08670dfd1e5b6..ee373c54bc5b31e28efe1ba346ecc5fd6d3f5652 100644
--- a/src/plugins/wp/wpo.mli
+++ b/src/plugins/wp/wpo.mli
@@ -234,6 +234,7 @@ val pp_logfile : Format.formatter -> t -> prover -> unit
 val pp_axiomatics : Format.formatter -> string option -> unit
 val pp_function : Format.formatter -> Kernel_function.t -> string option -> unit
 val pp_goal_flow : Format.formatter -> t -> unit
+val pp_flow : Format.formatter -> unit
 
 (* -------------------------------------------------------------------------- *)
 (* --- Generators                                                         --- *)
diff --git a/tests/builtins/oracle/free.res.oracle b/tests/builtins/oracle/free.res.oracle
index 1f95b2c0061d6e8413677644bcc0482f456e261e..4f5cb6ae56f07cb9ca6b0984d705f3d7a0d5965f 100644
--- a/tests/builtins/oracle/free.res.oracle
+++ b/tests/builtins/oracle/free.res.oracle
@@ -15,7 +15,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
diff --git a/tests/builtins/oracle/linked_list.0.res.oracle b/tests/builtins/oracle/linked_list.0.res.oracle
index c7cf1e9421823e655895d76109504721949c758a..61083435b7ad0833144f3dac32cd6b0b7545b794 100644
--- a/tests/builtins/oracle/linked_list.0.res.oracle
+++ b/tests/builtins/oracle/linked_list.0.res.oracle
@@ -15,12 +15,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -58,12 +58,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -97,12 +97,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -139,12 +139,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -180,12 +180,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -225,12 +225,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -268,12 +268,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -315,12 +315,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -360,12 +360,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -409,12 +409,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -456,12 +456,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -507,12 +507,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -800,12 +800,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -1095,12 +1095,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -1386,12 +1386,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -1681,12 +1681,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -1973,12 +1973,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -2269,12 +2269,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..2047] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
diff --git a/tests/builtins/oracle/linked_list.1.res.oracle b/tests/builtins/oracle/linked_list.1.res.oracle
index a6456f3e810b6a38cf5d9ac6b270397aa8ae9bde..ab1cd53fb4aa9ca57158e091604b734523bed717 100644
--- a/tests/builtins/oracle/linked_list.1.res.oracle
+++ b/tests/builtins/oracle/linked_list.1.res.oracle
@@ -15,12 +15,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -58,12 +58,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -97,12 +97,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -139,12 +139,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -180,12 +180,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -225,12 +225,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -268,12 +268,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -315,12 +315,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -360,12 +360,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -409,12 +409,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -457,12 +457,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -509,12 +509,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -556,12 +556,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -601,12 +601,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -642,12 +642,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -687,12 +687,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -731,12 +731,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -775,12 +775,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
diff --git a/tests/builtins/oracle/linked_list.2.res.oracle b/tests/builtins/oracle/linked_list.2.res.oracle
index 43dbed7de1ea30104b2d1febee8b01851ac22549..72eef5ce30bbac814bab7dad0c7a5340e4d6d28d 100644
--- a/tests/builtins/oracle/linked_list.2.res.oracle
+++ b/tests/builtins/oracle/linked_list.2.res.oracle
@@ -15,12 +15,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -58,12 +58,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -96,12 +96,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -138,12 +138,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -179,12 +179,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -224,12 +224,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -267,12 +267,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -314,12 +314,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -359,12 +359,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -408,12 +408,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -455,12 +455,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -506,12 +506,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -555,12 +555,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -608,12 +608,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -659,12 +659,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -714,12 +714,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -767,12 +767,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -824,12 +824,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -879,12 +879,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -938,12 +938,12 @@
   __fc_stdout ∈ {{ &__fc_initial_stdout }}
   __fc_fopen[0..15] ∈ {0}
   __fc_p_fopen ∈ {{ &__fc_fopen[0] }}
-  __fc_tmpnam[0..0x7FF] ∈ {0}
+  __fc_tmpnam[0..19] ∈ {0}
   __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }}
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {0x7FFF}
+  __fc_rand_max ∈ {0x7FFFFFFF}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
diff --git a/tests/builtins/oracle/malloc-size-zero.0.res.oracle b/tests/builtins/oracle/malloc-size-zero.0.res.oracle
index 144bf5624b341f5494df694a89dce00eaa23c34e..1b725ab6061ad2238e62ba1eff947b2aa979b398 100644
--- a/tests/builtins/oracle/malloc-size-zero.0.res.oracle
+++ b/tests/builtins/oracle/malloc-size-zero.0.res.oracle
@@ -50,7 +50,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
diff --git a/tests/builtins/oracle/malloc-size-zero.1.res.oracle b/tests/builtins/oracle/malloc-size-zero.1.res.oracle
index 79f6728188cf3d82355fdece2946fce400f57dac..511d5f834c36fd9081ee2e2bd86866fcb38c10d5 100644
--- a/tests/builtins/oracle/malloc-size-zero.1.res.oracle
+++ b/tests/builtins/oracle/malloc-size-zero.1.res.oracle
@@ -32,7 +32,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
diff --git a/tests/builtins/oracle/realloc.res.oracle b/tests/builtins/oracle/realloc.res.oracle
index 3441c23c27b3a9e7b8c34e0d64ae935f31a6a3cb..df107558a522d428e7c910802a4affbe07f80eb3 100644
--- a/tests/builtins/oracle/realloc.res.oracle
+++ b/tests/builtins/oracle/realloc.res.oracle
@@ -13,7 +13,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -41,7 +41,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -87,7 +87,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -129,7 +129,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -161,7 +161,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -226,7 +226,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -280,7 +280,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -342,7 +342,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -371,7 +371,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -436,7 +436,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -463,7 +463,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -501,7 +501,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -538,7 +538,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -576,7 +576,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -606,7 +606,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
diff --git a/tests/builtins/oracle/realloc_multiple.0.res.oracle b/tests/builtins/oracle/realloc_multiple.0.res.oracle
index 90a945812a66a13ef7723e9c41c1291ebedb8c47..5908db2b9e507a91de87ff057e31832be7b548e8 100644
--- a/tests/builtins/oracle/realloc_multiple.0.res.oracle
+++ b/tests/builtins/oracle/realloc_multiple.0.res.oracle
@@ -21,7 +21,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -56,7 +56,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -105,7 +105,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -142,7 +142,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -196,7 +196,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -238,7 +238,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -280,7 +280,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
diff --git a/tests/builtins/oracle/realloc_multiple.1.res.oracle b/tests/builtins/oracle/realloc_multiple.1.res.oracle
index 831c3434213e54c9259aee81a7a24548c3d49be5..052f0f273fa2a1f63c42e4ef5be7fa27b6c5d044 100644
--- a/tests/builtins/oracle/realloc_multiple.1.res.oracle
+++ b/tests/builtins/oracle/realloc_multiple.1.res.oracle
@@ -29,7 +29,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -64,7 +64,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -95,7 +95,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -150,7 +150,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -187,7 +187,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -222,7 +222,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -280,7 +280,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -326,7 +326,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -368,7 +368,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
diff --git a/tests/builtins/oracle/strnlen.res.oracle b/tests/builtins/oracle/strnlen.res.oracle
index 0853c554d1693daa487e1b60d57214326cceee9a..06fce1695a9043d52dd273ac7e84a54f3d19a130 100644
--- a/tests/builtins/oracle/strnlen.res.oracle
+++ b/tests/builtins/oracle/strnlen.res.oracle
@@ -37,7 +37,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
diff --git a/tests/builtins/oracle_gauges/realloc.res.oracle b/tests/builtins/oracle_gauges/realloc.res.oracle
index 05fc14b03b3cfda3926bac350cbafeacaa044e5e..7db5bb2855581132216cb4aff783b868c8fd005b 100644
--- a/tests/builtins/oracle_gauges/realloc.res.oracle
+++ b/tests/builtins/oracle_gauges/realloc.res.oracle
@@ -8,7 +8,7 @@
 >   # cvalue:
 >   __fc_heap_status ∈ [--..--]
 >   __fc_random_counter ∈ [--..--]
->   __fc_rand_max ∈ {32767}
+>   __fc_rand_max ∈ {2147483647}
 >   __fc_random48_init ∈ {0}
 >   __fc_random48_counter[0..2] ∈ [--..--]
 >   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -36,7 +36,7 @@
 >   # cvalue:
 >   __fc_heap_status ∈ [--..--]
 >   __fc_random_counter ∈ [--..--]
->   __fc_rand_max ∈ {32767}
+>   __fc_rand_max ∈ {2147483647}
 >   __fc_random48_init ∈ {0}
 >   __fc_random48_counter[0..2] ∈ [--..--]
 >   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -64,7 +64,7 @@
 >   # cvalue:
 >   __fc_heap_status ∈ [--..--]
 >   __fc_random_counter ∈ [--..--]
->   __fc_rand_max ∈ {32767}
+>   __fc_rand_max ∈ {2147483647}
 >   __fc_random48_init ∈ {0}
 >   __fc_random48_counter[0..2] ∈ [--..--]
 >   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -92,7 +92,7 @@
 >   # cvalue:
 >   __fc_heap_status ∈ [--..--]
 >   __fc_random_counter ∈ [--..--]
->   __fc_rand_max ∈ {32767}
+>   __fc_rand_max ∈ {2147483647}
 >   __fc_random48_init ∈ {0}
 >   __fc_random48_counter[0..2] ∈ [--..--]
 >   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -120,7 +120,7 @@
 >   # cvalue:
 >   __fc_heap_status ∈ [--..--]
 >   __fc_random_counter ∈ [--..--]
->   __fc_rand_max ∈ {32767}
+>   __fc_rand_max ∈ {2147483647}
 >   __fc_random48_init ∈ {0}
 >   __fc_random48_counter[0..2] ∈ [--..--]
 >   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -148,7 +148,7 @@
 >   # cvalue:
 >   __fc_heap_status ∈ [--..--]
 >   __fc_random_counter ∈ [--..--]
->   __fc_rand_max ∈ {32767}
+>   __fc_rand_max ∈ {2147483647}
 >   __fc_random48_init ∈ {0}
 >   __fc_random48_counter[0..2] ∈ [--..--]
 >   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -176,7 +176,7 @@
 >   # cvalue:
 >   __fc_heap_status ∈ [--..--]
 >   __fc_random_counter ∈ [--..--]
->   __fc_rand_max ∈ {32767}
+>   __fc_rand_max ∈ {2147483647}
 >   __fc_random48_init ∈ {0}
 >   __fc_random48_counter[0..2] ∈ [--..--]
 >   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -204,7 +204,7 @@
 >   # cvalue:
 >   __fc_heap_status ∈ [--..--]
 >   __fc_random_counter ∈ [--..--]
->   __fc_rand_max ∈ {32767}
+>   __fc_rand_max ∈ {2147483647}
 >   __fc_random48_init ∈ {0}
 >   __fc_random48_counter[0..2] ∈ [--..--]
 >   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -232,7 +232,7 @@
 >   # cvalue:
 >   __fc_heap_status ∈ [--..--]
 >   __fc_random_counter ∈ [--..--]
->   __fc_rand_max ∈ {32767}
+>   __fc_rand_max ∈ {2147483647}
 >   __fc_random48_init ∈ {0}
 >   __fc_random48_counter[0..2] ∈ [--..--]
 >   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -261,7 +261,7 @@
 >   # cvalue:
 >   __fc_heap_status ∈ [--..--]
 >   __fc_random_counter ∈ [--..--]
->   __fc_rand_max ∈ {32767}
+>   __fc_rand_max ∈ {2147483647}
 >   __fc_random48_init ∈ {0}
 >   __fc_random48_counter[0..2] ∈ [--..--]
 >   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -289,7 +289,7 @@
 >   # cvalue:
 >   __fc_heap_status ∈ [--..--]
 >   __fc_random_counter ∈ [--..--]
->   __fc_rand_max ∈ {32767}
+>   __fc_rand_max ∈ {2147483647}
 >   __fc_random48_init ∈ {0}
 >   __fc_random48_counter[0..2] ∈ [--..--]
 >   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -317,7 +317,7 @@
 >   # cvalue:
 >   __fc_heap_status ∈ [--..--]
 >   __fc_random_counter ∈ [--..--]
->   __fc_rand_max ∈ {32767}
+>   __fc_rand_max ∈ {2147483647}
 >   __fc_random48_init ∈ {0}
 >   __fc_random48_counter[0..2] ∈ [--..--]
 >   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
diff --git a/tests/float/oracle/const1.res.oracle b/tests/float/oracle/const1.res.oracle
index a843cb7cf3b3001cd1594f0f21aa7148c4b6b5d4..8fbb1ef225d90d95581c0e8b293af2795ff5da08 100644
--- a/tests/float/oracle/const1.res.oracle
+++ b/tests/float/oracle/const1.res.oracle
@@ -5,7 +5,7 @@
 [eva] Analyzing a complete application starting at main
 [eva] Computing initial state
 [eva:alarm] const1.i:1: Warning: 
-  non-finite float value. assert \is_finite((float)1e40f);
+  non-finite float value. assert \is_finite(1e40f);
 [eva] const1.i:1: Warning: 
   evaluation of initializer '(unsigned long long)1e40f' failed
 [eva] Initial state computed
diff --git a/tests/float/oracle/const2.res.oracle b/tests/float/oracle/const2.res.oracle
index 94744b2de338fad025efb90e4b9908e02488725a..8dd6596c994a7f134c54f94a632b43f205e9c061 100644
--- a/tests/float/oracle/const2.res.oracle
+++ b/tests/float/oracle/const2.res.oracle
@@ -5,7 +5,7 @@
 [eva] Analyzing a complete application starting at main
 [eva] Computing initial state
 [eva:alarm] const2.i:2: Warning: 
-  non-finite float value. assert \is_finite((float)1e40f);
+  non-finite float value. assert \is_finite(1e40f);
 [eva] const2.i:2: Warning: evaluation of initializer '1e40f' failed
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
diff --git a/tests/float/oracle/const4.0.res.oracle b/tests/float/oracle/const4.0.res.oracle
index fa336743685bb9299c681af68b70f7df506c97d1..6582b5a74178ba39ffb450f0d02a75fb248d2a60 100644
--- a/tests/float/oracle/const4.0.res.oracle
+++ b/tests/float/oracle/const4.0.res.oracle
@@ -6,7 +6,7 @@
 [eva] Analyzing a complete application starting at main
 [eva] Computing initial state
 [eva:alarm] const4.i:7: Warning: 
-  non-finite float value. assert \is_finite((float)3.405e38f);
+  non-finite float value. assert \is_finite(3.405e38f);
 [eva] const4.i:7: Warning: evaluation of initializer '(double)3.405e38f' failed
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
diff --git a/tests/float/oracle/const4.1.res.oracle b/tests/float/oracle/const4.1.res.oracle
index 85a2c33e173e9932409b5cc8a4778d10b568ec68..8854b8b2448d6cd9fd7ec98ede98a3d0cbabde8b 100644
--- a/tests/float/oracle/const4.1.res.oracle
+++ b/tests/float/oracle/const4.1.res.oracle
@@ -8,7 +8,7 @@
 [eva] Analyzing a complete application starting at main
 [eva] Computing initial state
 [eva:alarm] const4.i:7: Warning: 
-  non-finite float value. assert \is_finite((float)3.405e38f);
+  non-finite float value. assert \is_finite(3.405e38f);
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
   f1 ∈ [3.39999995214e+38 .. 3.40000015497e+38]
diff --git a/tests/float/oracle/cte_overflow.res.oracle b/tests/float/oracle/cte_overflow.res.oracle
index 50328773570d84b2cc7982447936bb3466e625f3..d7287cf5d95221001a911e1a0f56f073a9be7f31 100644
--- a/tests/float/oracle/cte_overflow.res.oracle
+++ b/tests/float/oracle/cte_overflow.res.oracle
@@ -15,7 +15,7 @@
 [eva:alarm] cte_overflow.i:12: Warning: 
   non-finite double value. assert \is_finite((double)1e500);
 [eva:alarm] cte_overflow.i:17: Warning: 
-  non-finite float value. assert \is_finite((float)1e80f);
+  non-finite float value. assert \is_finite(1e80f);
 [eva] Recording results for main
 [eva] done for function main
 [eva] cte_overflow.i:12: 
diff --git a/tests/float/oracle/parse.res.oracle b/tests/float/oracle/parse.res.oracle
index f9c65e85c126e12b56abc0f52d25d2027bd2b99e..57d0b1b1bce9064e56bc30a472ca0c93a691c1fd 100644
--- a/tests/float/oracle/parse.res.oracle
+++ b/tests/float/oracle/parse.res.oracle
@@ -18,7 +18,7 @@
 [eva] parse.i:36: Warning: 
   cannot parse floating-point constant, returning imprecise result
 [eva:alarm] parse.i:36: Warning: 
-  non-finite long double value. assert \is_finite((long double)0x1p32767L);
+  non-finite long double value. assert \is_finite(0x1p32767L);
 [eva:alarm] parse.i:37: Warning: 
   non-finite long double value. assert \is_finite(l);
 [eva:alarm] parse.i:37: Warning: 
diff --git a/tests/idct/oracle/ieee_1180_1990.res.oracle b/tests/idct/oracle/ieee_1180_1990.res.oracle
index 2b84b5e6d38b4bc9695b2eac24820d8a7b12bfde..76dc3eb09e9db269d984133d66acb38c400de4a7 100644
--- a/tests/idct/oracle/ieee_1180_1990.res.oracle
+++ b/tests/idct/oracle/ieee_1180_1990.res.oracle
@@ -1136,16 +1136,15 @@
               \result ≡ __fc_p_tmpnam
             Unverifiable but considered Valid.
 [ Extern  ] Assigns (file FRAMAC_SHARE/libc/stdio.h, line 109)
-            assigns *(__fc_p_tmpnam + (0 .. 2048)), *(s + (0 .. 2048)),
-                    \result;
+            assigns *(__fc_p_tmpnam + (0 .. 20)), *(s + (0 .. 20)), \result;
             Unverifiable but considered Valid.
 [ Extern  ] Froms (file FRAMAC_SHARE/libc/stdio.h, line 109)
-            assigns *(__fc_p_tmpnam + (0 .. 2048))
-              \from *(__fc_p_tmpnam + (0 .. 2048)), (indirect: s);
+            assigns *(__fc_p_tmpnam + (0 .. 20))
+              \from *(__fc_p_tmpnam + (0 .. 20)), (indirect: s);
             Unverifiable but considered Valid.
 [ Extern  ] Froms (file FRAMAC_SHARE/libc/stdio.h, line 111)
-            assigns *(s + (0 .. 2048))
-              \from (indirect: s), *(__fc_p_tmpnam + (0 .. 2048));
+            assigns *(s + (0 .. 20))
+              \from (indirect: s), *(__fc_p_tmpnam + (0 .. 20));
             Unverifiable but considered Valid.
 [ Extern  ] Froms (file FRAMAC_SHARE/libc/stdio.h, line 112)
             assigns \result \from s, __fc_p_tmpnam;
@@ -1426,7 +1425,7 @@
 
 [ Extern  ] Post-condition 'result_uchar_or_eof'
             ensures
-            result_uchar_or_eof: (0 ≤ \result ≤ 255) ∨ \result ≡ -1
+            result_uchar_or_eof: (0 ≤ \result ≤ 255U) ∨ \result ≡ -1
             Unverifiable but considered Valid.
 [ Extern  ] Assigns (file FRAMAC_SHARE/libc/stdio.h, line 261)
             assigns *stream, \result;
diff --git a/tests/idct/oracle_multidim/ieee_1180_1990.res.oracle b/tests/idct/oracle_multidim/ieee_1180_1990.res.oracle
index 51a1a894ad988e333fa9e44015a7e7498df8a2d8..47aa5d3e5dd20d6f1977724377123cb11af05543 100644
--- a/tests/idct/oracle_multidim/ieee_1180_1990.res.oracle
+++ b/tests/idct/oracle_multidim/ieee_1180_1990.res.oracle
@@ -265,7 +265,7 @@
 <      "output.\n"[bits 0 to 71]
 ---
 >     idct_init; idct_mc1[0..7][0..7]; idct_mc2[0..7][0..7]
-3910,3932d3744
+3909,3931d3743
 < [    -    ] Assertion 'Eva,initialization' (file idct.c, line 129)
 <             assert Eva: initialization: \initialized(&tmp1[i][j]);
 <             tried with Eva.
@@ -289,7 +289,7 @@
 <             assert Eva: initialization: \initialized(&tmp1[i][j]);
 <             By RedundantAlarms, with pending:
 <              - Assertion 'Eva,initialization' (file idct.c, line 145)
-3936,3958d3747
+3935,3957d3746
 < [    -    ] Assertion 'Eva,initialization' (file idct.c, line 163)
 <             assert Eva: initialization: \initialized(&tmp1[i][j]);
 <             tried with Eva.
@@ -313,11 +313,11 @@
 <             assert Eva: initialization: \initialized(&tmp1[i][j]);
 <             By RedundantAlarms, with pending:
 <              - Assertion 'Eva,initialization' (file idct.c, line 180)
-3980,3982d3768
+3979,3981d3767
 < [    -    ] Assertion 'Eva,initialization' (file ieee_1180_1990.c, line 109)
 <             assert Eva: initialization: \initialized(&tmp1[i][j]);
 <             tried with Eva.
-3986,4019d3771
+3985,4018d3770
 < [    -    ] Assertion 'Eva,initialization' (file ieee_1180_1990.c, line 116)
 <             assert Eva: initialization: \initialized(&tmp2[i][j]);
 <             tried with Eva.
@@ -352,11 +352,11 @@
 < [    -    ] Assertion 'Eva,float_to_int' (file ieee_1180_1990.c, line 124)
 <             assert Eva: float_to_int: tmp2[i][j] - 0.5 < 2147483648;
 <             tried with Eva.
-4040,4042d3791
+4039,4041d3790
 < [    -    ] Assertion 'Eva,initialization' (file ieee_1180_1990.c, line 150)
 <             assert Eva: initialization: \initialized(&tmp1[i][j]);
 <             tried with Eva.
-4046,4079d3794
+4045,4078d3793
 < [    -    ] Assertion 'Eva,initialization' (file ieee_1180_1990.c, line 157)
 <             assert Eva: initialization: \initialized(&tmp2[i][j]);
 <             tried with Eva.
@@ -391,7 +391,7 @@
 < [    -    ] Assertion 'Eva,float_to_int' (file ieee_1180_1990.c, line 165)
 <             assert Eva: float_to_int: tmp2[i][j] - 0.5 < 2147483648;
 <             tried with Eva.
-4179,4195c3894,3900
+4178,4194c3893,3899
 < [ Partial ] Assertion 'Eva,initialization' (file ieee_1180_1990.c, line 358)
 <             assert Eva: initialization: \initialized(&res[i].pmse[j][k]);
 <             By RedundantAlarms, with pending:
@@ -417,7 +417,7 @@
 >             reachability of stmt line 196 in main
 >             by Eva.
 > [  Dead   ] Instance of 'Pre-condition (file FRAMAC_SHARE/libc/stdio.h, line 211)' at call 'printf_va_1' (file ieee_1180_1990.c, line 195)
-4199,4200c3904,3907
+4198,4199c3903,3906
 <             by Eva.
 < [  Valid  ] Instance of 'Pre-condition (file FRAMAC_SHARE/libc/stdio.h, line 211)' at call 'printf_va_2' (file ieee_1180_1990.c, line 196)
 ---
@@ -425,18 +425,18 @@
 >             By Eva because:
 >              - Unreachable call 'printf_va_1' (file ieee_1180_1990.c, line 195)
 > [  Dead   ] Instance of 'Pre-condition (file FRAMAC_SHARE/libc/stdio.h, line 211)' at call 'printf_va_2' (file ieee_1180_1990.c, line 196)
-4204c3911,3913
+4203c3910,3912
 <             by Eva.
 ---
 >             Locally valid, but unreachable.
 >             By Eva because:
 >              - Unreachable call 'printf_va_2' (file ieee_1180_1990.c, line 196)
-4261,4262c3970
+4260,4261c3969
 <    194 Completely validated
 <     16 Locally validated
 ---
 >    192 Completely validated
-4264,4265c3972,3975
+4263,4264c3971,3974
 <     56 To be validated
 <    836 Total
 ---
diff --git a/tests/libc/fc_builtin_c.c b/tests/libc/fc_builtin_c.c
index ea336b1e04e74964ed8d1f4be98dbe91cc52e110..abd1f7ce3defdd44419c38365fc2ce69d680f3b8 100644
--- a/tests/libc/fc_builtin_c.c
+++ b/tests/libc/fc_builtin_c.c
@@ -34,4 +34,11 @@ int main() {
     Frama_C_unsigned_long_interval(LONG_MAX - 1UL, LONG_MAX + 1UL);
   //@ assert bounds: LONG_MAX - 1 <= ul <= LONG_MAX + 1;
   //@ assert sampling:unknown: ul == LONG_MAX;
+
+#ifdef __WORDSIZE
+  int w = __WORDSIZE;
+#else
+  int w = -1;
+#endif
+  //@ assert __WORDSIZE_is_defined: w > 0;
 }
diff --git a/tests/libc/limits_h.c b/tests/libc/limits_h.c
index 2c663b2c5645c1ac80856c0c08a53b438939debf..54c08b971f7eb3f03fbe707e6634b41e55940517 100644
--- a/tests/libc/limits_h.c
+++ b/tests/libc/limits_h.c
@@ -7,6 +7,8 @@
   STDOPT: +"-machdep gcc_x86_64"
   STDOPT: +"-machdep ppc_32"
   STDOPT: +"-machdep msvc_x86_64"
+  STDOPT: +"-machdep avr_8"
+  STDOPT: +"-machdep avr_16"
 */
 #include <sys/types.h>
 #include <stdint.h>
diff --git a/tests/libc/oracle/fc_builtin_c.res.oracle b/tests/libc/oracle/fc_builtin_c.res.oracle
index d922ab4e1efacfb6929daebe1b0ce6160246ba19..6ca7e87a24c415fee903563b95ff56478deaecd8 100644
--- a/tests/libc/oracle/fc_builtin_c.res.oracle
+++ b/tests/libc/oracle/fc_builtin_c.res.oracle
@@ -73,6 +73,7 @@
 [eva] fc_builtin_c.c:35: assertion 'bounds' got status valid.
 [eva:alarm] fc_builtin_c.c:36: Warning: 
   assertion 'sampling,unknown' got status unknown.
+[eva] fc_builtin_c.c:43: assertion '__WORDSIZE_is_defined' got status valid.
 [eva] Recording results for main
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
@@ -111,4 +112,5 @@
   d ∈ [12345678901.2 .. 12345678901.2]
   l ∈ {-3}
   ul ∈ {2147483647}
+  w ∈ {32}
   __retres ∈ {0}
diff --git a/tests/libc/oracle/fc_libc.1.res.oracle b/tests/libc/oracle/fc_libc.1.res.oracle
index 45092e46f291f3ead9cfe6dae97543f9ee079c99..af69919cfaada999bd2993b0d2fbe07eda3e0625 100644
--- a/tests/libc/oracle/fc_libc.1.res.oracle
+++ b/tests/libc/oracle/fc_libc.1.res.oracle
@@ -1,7 +1,7 @@
 [kernel] Parsing fc_libc.c (with preprocessing)
 /* Generated by Frama-C */
 typedef unsigned int size_t;
-typedef int wchar_t;
+typedef long wchar_t;
 struct __fc_div_t {
    int quot ;
    int rem ;
@@ -773,7 +773,7 @@ axiomatic WMemChr {
   
   axiom wmemchr_def{L}:
     ∀ wchar_t *s;
-    ∀ int c;
+    ∀ long c;
     ∀ ℤ n;
       wmemchr(s, c, n) ≡ \true ⇔
       (∃ int i; 0 ≤ i < n ∧ *(s + i) ≡ c);
@@ -1162,7 +1162,7 @@ extern unsigned long long strtoull(char const * restrict nptr,
 
 /*@ ghost extern int __fc_random_counter __attribute__((__unused__)); */
 
-unsigned long const __fc_rand_max = (unsigned long)32767;
+unsigned long const __fc_rand_max = (unsigned long)2147483647;
 /*@ ensures result_range: 0 ≤ \result ≤ __fc_rand_max;
     assigns \result, __fc_random_counter;
     assigns \result \from __fc_random_counter;
@@ -3523,8 +3523,7 @@ extern float frexpf(float x, int *exp);
 extern long double frexpl(long double x, int *exp);
 
 /*@ requires
-      finite_logic_res:
-        \is_finite((double)(x * pow((double)2.0d, (double)exp)));
+      finite_logic_res: \is_finite((double)(x * pow(2.0d, (double)exp)));
     ensures finite_result: \is_finite(\result);
     ensures
       __fc_errno: __fc_errno ≡ 34 ∨ __fc_errno ≡ \old(__fc_errno);
@@ -3536,8 +3535,7 @@ extern double ldexp(double x, int exp);
 
 /*@ requires
       finite_logic_res:
-        \is_finite((float)(x *
-                           pow((double)((float)2.0f), (double)((float)exp))));
+        \is_finite((float)(x * pow((double)(2.0f), (double)((float)exp))));
     ensures finite_result: \is_finite(\result);
     ensures
       __fc_errno: __fc_errno ≡ 34 ∨ __fc_errno ≡ \old(__fc_errno);
@@ -4070,7 +4068,7 @@ extern int volatile __fc_fds[1024];
           0 ≤ i < iovcnt ⇒
           \valid((char *)(&(iov + i)->iov_base) +
                  (0 .. (iov + i)->iov_len - 1));
-    requires bounded_iovcnt: 0 ≤ iovcnt ≤ 1024;
+    requires bounded_iovcnt: 0 ≤ iovcnt ≤ 255;
     ensures
       result_error_or_read_bytes:
         \result ≡ -1 ∨
@@ -4103,7 +4101,7 @@ extern ssize_t readv(int fd, struct iovec const *iov, int iovcnt);
           0 ≤ i < iovcnt ⇒
           \valid_read((char *)(iov + i)->iov_base +
                       (0 .. (iov + i)->iov_len - 1));
-    requires bounded_iovcnt: 0 ≤ iovcnt ≤ 1024;
+    requires bounded_iovcnt: 0 ≤ iovcnt ≤ 255;
     requires
       bounded_lengths:
         \sum(0, iovcnt - 1, \lambda ℤ k; (iov + k)->iov_len) ≤ 2147483647;
@@ -4555,19 +4553,19 @@ int getaddrinfo(char const * restrict nodename,
       }
       tmp_3 = Frama_C_interval(0,43);
       sa->sa_family = (sa_family_t)tmp_3;
-      /*@ slevel 15; */
+      /*@ slevel 15; */ ;
       {
         int i = 0;
         while (i < 14) {
           {
             int tmp_4;
-            tmp_4 = Frama_C_interval(-128,127);
+            tmp_4 = Frama_C_interval(-127 - 1,127);
             sa->sa_data[i] = (char)tmp_4;
           }
           i ++;
         }
       }
-      /*@ slevel default; */
+      /*@ slevel default; */ ;
       ai->ai_flags = 0;
       ai->ai_family = (int)sa->sa_family;
       ai->ai_socktype = Frama_C_interval(0,5);
@@ -4597,7 +4595,7 @@ static int res_search(char const *dname, int rec_class, int type,
   {
     int i = 0;
     while (i < anslen - 1) {
-      *(answer + i) = Frama_C_char_interval((char)(-128),(char)127);
+      *(answer + i) = Frama_C_char_interval((char)(-127 - 1),(char)127);
       i ++;
     }
   }
@@ -6065,18 +6063,18 @@ FILE * const __fc_p_fopen = __fc_fopen;
  */
 extern FILE *tmpfile(void);
 
-char __fc_tmpnam[2048];
+char __fc_tmpnam[20];
 char * const __fc_p_tmpnam = __fc_tmpnam;
-/*@ requires valid_s_or_null: s ≡ \null ∨ \valid(s + (0 .. 2048));
+/*@ requires valid_s_or_null: s ≡ \null ∨ \valid(s + (0 .. 20));
     ensures
       result_string_or_null:
         \result ≡ \null ∨ \result ≡ \old(s) ∨
         \result ≡ __fc_p_tmpnam;
-    assigns *(__fc_p_tmpnam + (0 .. 2048)), *(s + (0 .. 2048)), \result;
-    assigns *(__fc_p_tmpnam + (0 .. 2048))
-      \from *(__fc_p_tmpnam + (0 .. 2048)), (indirect: s);
-    assigns *(s + (0 .. 2048))
-      \from (indirect: s), *(__fc_p_tmpnam + (0 .. 2048));
+    assigns *(__fc_p_tmpnam + (0 .. 20)), *(s + (0 .. 20)), \result;
+    assigns *(__fc_p_tmpnam + (0 .. 20))
+      \from *(__fc_p_tmpnam + (0 .. 20)), (indirect: s);
+    assigns *(s + (0 .. 20))
+      \from (indirect: s), *(__fc_p_tmpnam + (0 .. 20));
     assigns \result \from s, __fc_p_tmpnam;
  */
 extern char *tmpnam(char *s);
@@ -6729,7 +6727,7 @@ char *fgets(char * restrict s, int size, FILE * restrict stream)
         __retres = s;
         goto return_label;
       }
-      tmp_2 = Frama_C_interval(-128,127);
+      tmp_2 = Frama_C_interval(-127 - 1,127);
       char c = (char)tmp_2;
       *(s + i) = c;
       if ((int)c == '\n') {
@@ -6746,7 +6744,7 @@ char *fgets(char * restrict s, int size, FILE * restrict stream)
 }
 
 /*@ requires valid_stream: \valid(stream);
-    ensures result_uchar_or_eof: (0 ≤ \result ≤ 255) ∨ \result ≡ -1;
+    ensures result_uchar_or_eof: (0 ≤ \result ≤ 255U) ∨ \result ≡ -1;
     assigns *stream, \result;
     assigns *stream \from *stream;
     assigns \result \from (indirect: *stream);
@@ -6774,7 +6772,7 @@ int fgetc(FILE * restrict stream)
   else {
     unsigned char tmp_1;
     tmp_1 = Frama_C_unsigned_char_interval((unsigned char)0,
-                                           (unsigned char)255);
+                                           (unsigned char)255U);
     __retres = (int)tmp_1;
     goto return_label;
   }
@@ -7227,9 +7225,9 @@ char *realpath(char const * restrict file_name, char * restrict resolved_name)
     goto return_label;
     default: break;
   }
-  int realpath_len = Frama_C_interval(1,256);
+  int realpath_len = Frama_C_interval(1,4096);
   if (! resolved_name) {
-    resolved_name = (char *)malloc((size_t)256);
+    resolved_name = (char *)malloc((size_t)4096);
     if (! resolved_name) {
       __fc_errno = 12;
       __retres = (char *)0;
@@ -8609,7 +8607,8 @@ int getopt(int argc, char * const *argv, char const *optstring)
   optarg = (char *)Frama_C_nondet_ptr((void *)0,
                                       (void *)(*(argv + nondet_ind) + nondet_indlen));
   optind = Frama_C_interval(1,argc + 1);
-  tmp_2 = Frama_C_unsigned_char_interval((unsigned char)0,(unsigned char)255);
+  tmp_2 = Frama_C_unsigned_char_interval((unsigned char)0,
+                                         (unsigned char)255U);
   tmp_3 = Frama_C_nondet(-1,(int)tmp_2);
   __retres = tmp_3;
   return_label: return __retres;
@@ -8679,11 +8678,11 @@ wchar_t *wcscpy(wchar_t *dest, wchar_t const *src)
 {
   size_t i;
   i = (size_t)0;
-  while (*(src + i) != 0) {
+  while (*(src + i) != 0L) {
     *(dest + i) = *(src + i);
     i ++;
   }
-  *(dest + i) = 0;
+  *(dest + i) = 0L;
   return dest;
 }
 
@@ -8696,7 +8695,7 @@ size_t wcslen(wchar_t const *str)
 {
   size_t i;
   i = (size_t)0;
-  while (*(str + i) != 0) i ++;
+  while (*(str + i) != 0L) i ++;
   return i;
 }
 
@@ -8718,11 +8717,11 @@ wchar_t *wcsncpy(wchar_t *dest, wchar_t const *src, size_t n)
   i = (size_t)0;
   while (i < n) {
     *(dest + i) = *(src + i);
-    if (*(src + i) == 0) break;
+    if (*(src + i) == 0L) break;
     i ++;
   }
   while (i < n) {
-    *(dest + i) = 0;
+    *(dest + i) = 0L;
     i ++;
   }
   return dest;
@@ -8750,11 +8749,11 @@ wchar_t *wcscat(wchar_t *dest, wchar_t const *src)
   size_t i;
   size_t n = wcslen((wchar_t const *)dest);
   i = (size_t)0;
-  while (*(src + i) != 0) {
+  while (*(src + i) != 0L) {
     *(dest + (n + i)) = *(src + i);
     i ++;
   }
-  *(dest + (n + i)) = 0;
+  *(dest + (n + i)) = 0L;
   return dest;
 }
 
@@ -8782,13 +8781,13 @@ wchar_t *wcsncat(wchar_t *dest, wchar_t const *src, size_t n)
   i = (size_t)0;
   while (1) {
     if (i < n) {
-      if (! (*(src + i) != 0)) break;
+      if (! (*(src + i) != 0L)) break;
     }
     else break;
     *(dest + (dest_len + i)) = *(src + i);
     i ++;
   }
-  *(dest + (dest_len + i)) = 0;
+  *(dest + (dest_len + i)) = 0L;
   return dest;
 }
 
@@ -10212,7 +10211,7 @@ extern int iconv_close(iconv_t __x0);
  */
 extern iconv_t iconv_open(char const *tocode, char const *fromcode);
 
-extern char __fc_basename[256];
+extern char __fc_basename[4096];
 
 char *__fc_p_basename = __fc_basename;
 /*@ requires
@@ -10227,7 +10226,7 @@ char *__fc_p_basename = __fc_basename;
  */
 extern char *basename(char *path);
 
-extern char __fc_dirname[256];
+extern char __fc_dirname[4096];
 
 char *__fc_p_dirname = __fc_dirname;
 /*@ requires
diff --git a/tests/libc/oracle/fc_libc.2.res.oracle b/tests/libc/oracle/fc_libc.2.res.oracle
index dc3e1747f8b51da5427112734c10885ea157d00a..b8e07f4d5104574e045c2d0751cfc89acda935f0 100644
--- a/tests/libc/oracle/fc_libc.2.res.oracle
+++ b/tests/libc/oracle/fc_libc.2.res.oracle
@@ -44,8 +44,6 @@
 [kernel] Parsing FRAMAC_SHARE/libc/__fc_inet.h (with preprocessing)
 [kernel] Parsing FRAMAC_SHARE/libc/__fc_integer.h (with preprocessing)
 [kernel] Parsing FRAMAC_SHARE/libc/__fc_libc.h (with preprocessing)
-[kernel] Parsing FRAMAC_SHARE/libc/__fc_machdep.h (with preprocessing)
-skipping FRAMAC_SHARE/libc/__fc_machdep_linux_shared.h
 [kernel] Parsing FRAMAC_SHARE/libc/__fc_select.h (with preprocessing)
 [kernel] Parsing FRAMAC_SHARE/libc/__fc_string_axiomatic.h (with preprocessing)
 [kernel] Parsing FRAMAC_SHARE/libc/aio.h (with preprocessing)
diff --git a/tests/libc/oracle/inttypes_h.2.res.oracle b/tests/libc/oracle/inttypes_h.2.res.oracle
index 92f400d2eb09f2eaf2e35ed7bd2037d5632d7974..df0cd81b6ed3724ab9a3a7826de79ae61ef9ba46 100644
--- a/tests/libc/oracle/inttypes_h.2.res.oracle
+++ b/tests/libc/oracle/inttypes_h.2.res.oracle
@@ -1641,7 +1641,7 @@ int printf_va_54(char const * restrict format, int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_55(char const * restrict format, int *param0);
+int scanf_va_55(char const * restrict format, long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1654,7 +1654,7 @@ int scanf_va_55(char const * restrict format, int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_55(char const * restrict format, int param0);
+int printf_va_55(char const * restrict format, long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1671,7 +1671,7 @@ int printf_va_55(char const * restrict format, int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_56(char const * restrict format, int *param0);
+int scanf_va_56(char const * restrict format, long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1684,7 +1684,7 @@ int scanf_va_56(char const * restrict format, int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_56(char const * restrict format, int param0);
+int printf_va_56(char const * restrict format, long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1701,7 +1701,7 @@ int printf_va_56(char const * restrict format, int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_57(char const * restrict format, unsigned int *param0);
+int scanf_va_57(char const * restrict format, unsigned long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1714,7 +1714,7 @@ int scanf_va_57(char const * restrict format, unsigned int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_57(char const * restrict format, unsigned int param0);
+int printf_va_57(char const * restrict format, unsigned long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1731,7 +1731,7 @@ int printf_va_57(char const * restrict format, unsigned int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_58(char const * restrict format, unsigned int *param0);
+int scanf_va_58(char const * restrict format, unsigned long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1744,7 +1744,7 @@ int scanf_va_58(char const * restrict format, unsigned int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_58(char const * restrict format, unsigned int param0);
+int printf_va_58(char const * restrict format, unsigned long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1761,7 +1761,7 @@ int printf_va_58(char const * restrict format, unsigned int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_59(char const * restrict format, unsigned int *param0);
+int scanf_va_59(char const * restrict format, unsigned long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1774,7 +1774,7 @@ int scanf_va_59(char const * restrict format, unsigned int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_59(char const * restrict format, unsigned int param0);
+int printf_va_59(char const * restrict format, unsigned long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1791,7 +1791,7 @@ int printf_va_59(char const * restrict format, unsigned int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_60(char const * restrict format, unsigned int *param0);
+int scanf_va_60(char const * restrict format, unsigned long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1804,7 +1804,7 @@ int scanf_va_60(char const * restrict format, unsigned int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_60(char const * restrict format, unsigned int param0);
+int printf_va_60(char const * restrict format, unsigned long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1821,7 +1821,7 @@ int printf_va_60(char const * restrict format, unsigned int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_61(char const * restrict format, int *param0);
+int scanf_va_61(char const * restrict format, long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1834,7 +1834,7 @@ int scanf_va_61(char const * restrict format, int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_61(char const * restrict format, int param0);
+int printf_va_61(char const * restrict format, long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1851,7 +1851,7 @@ int printf_va_61(char const * restrict format, int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_62(char const * restrict format, int *param0);
+int scanf_va_62(char const * restrict format, long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1864,7 +1864,7 @@ int scanf_va_62(char const * restrict format, int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_62(char const * restrict format, int param0);
+int printf_va_62(char const * restrict format, long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1881,7 +1881,7 @@ int printf_va_62(char const * restrict format, int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_63(char const * restrict format, unsigned int *param0);
+int scanf_va_63(char const * restrict format, unsigned long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1894,7 +1894,7 @@ int scanf_va_63(char const * restrict format, unsigned int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_63(char const * restrict format, unsigned int param0);
+int printf_va_63(char const * restrict format, unsigned long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1911,7 +1911,7 @@ int printf_va_63(char const * restrict format, unsigned int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_64(char const * restrict format, unsigned int *param0);
+int scanf_va_64(char const * restrict format, unsigned long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1924,7 +1924,7 @@ int scanf_va_64(char const * restrict format, unsigned int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_64(char const * restrict format, unsigned int param0);
+int printf_va_64(char const * restrict format, unsigned long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1941,7 +1941,7 @@ int printf_va_64(char const * restrict format, unsigned int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_65(char const * restrict format, unsigned int *param0);
+int scanf_va_65(char const * restrict format, unsigned long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1954,7 +1954,7 @@ int scanf_va_65(char const * restrict format, unsigned int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_65(char const * restrict format, unsigned int param0);
+int printf_va_65(char const * restrict format, unsigned long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1971,7 +1971,7 @@ int printf_va_65(char const * restrict format, unsigned int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_66(char const * restrict format, unsigned int *param0);
+int scanf_va_66(char const * restrict format, unsigned long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1984,7 +1984,7 @@ int scanf_va_66(char const * restrict format, unsigned int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_66(char const * restrict format, unsigned int param0);
+int printf_va_66(char const * restrict format, unsigned long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -2693,39 +2693,39 @@ int main(void)
   }
   {
     int_fast16_t x_17;
-    scanf("%d",& x_17); /* scanf_va_55 */
-    printf("%d",x_17); /* printf_va_55 */
-    scanf("%i",& x_17); /* scanf_va_56 */
-    printf("%i",x_17); /* printf_va_56 */
+    scanf("%ld",& x_17); /* scanf_va_55 */
+    printf("%ld",x_17); /* printf_va_55 */
+    scanf("%li",& x_17); /* scanf_va_56 */
+    printf("%li",x_17); /* printf_va_56 */
   }
   {
     uint_fast16_t x_18;
-    scanf("%o",& x_18); /* scanf_va_57 */
-    printf("%o",x_18); /* printf_va_57 */
-    scanf("%u",& x_18); /* scanf_va_58 */
-    printf("%u",x_18); /* printf_va_58 */
-    scanf("%x",& x_18); /* scanf_va_59 */
-    printf("%x",x_18); /* printf_va_59 */
-    scanf("%x",& x_18); /* scanf_va_60 */
-    printf("%X",x_18); /* printf_va_60 */
+    scanf("%lo",& x_18); /* scanf_va_57 */
+    printf("%lo",x_18); /* printf_va_57 */
+    scanf("%lu",& x_18); /* scanf_va_58 */
+    printf("%lu",x_18); /* printf_va_58 */
+    scanf("%lx",& x_18); /* scanf_va_59 */
+    printf("%lx",x_18); /* printf_va_59 */
+    scanf("%lx",& x_18); /* scanf_va_60 */
+    printf("%lX",x_18); /* printf_va_60 */
   }
   {
     int_fast32_t x_19;
-    scanf("%d",& x_19); /* scanf_va_61 */
-    printf("%d",x_19); /* printf_va_61 */
-    scanf("%i",& x_19); /* scanf_va_62 */
-    printf("%i",x_19); /* printf_va_62 */
+    scanf("%ld",& x_19); /* scanf_va_61 */
+    printf("%ld",x_19); /* printf_va_61 */
+    scanf("%li",& x_19); /* scanf_va_62 */
+    printf("%li",x_19); /* printf_va_62 */
   }
   {
     uint_fast32_t x_20;
-    scanf("%o",& x_20); /* scanf_va_63 */
-    printf("%o",x_20); /* printf_va_63 */
-    scanf("%u",& x_20); /* scanf_va_64 */
-    printf("%u",x_20); /* printf_va_64 */
-    scanf("%x",& x_20); /* scanf_va_65 */
-    printf("%x",x_20); /* printf_va_65 */
-    scanf("%x",& x_20); /* scanf_va_66 */
-    printf("%X",x_20); /* printf_va_66 */
+    scanf("%lo",& x_20); /* scanf_va_63 */
+    printf("%lo",x_20); /* printf_va_63 */
+    scanf("%lu",& x_20); /* scanf_va_64 */
+    printf("%lu",x_20); /* printf_va_64 */
+    scanf("%lx",& x_20); /* scanf_va_65 */
+    printf("%lx",x_20); /* printf_va_65 */
+    scanf("%lx",& x_20); /* scanf_va_66 */
+    printf("%lX",x_20); /* printf_va_66 */
   }
   {
     int_fast64_t x_21;
diff --git a/tests/libc/oracle/inttypes_h.5.res.oracle b/tests/libc/oracle/inttypes_h.5.res.oracle
index 92f400d2eb09f2eaf2e35ed7bd2037d5632d7974..df0cd81b6ed3724ab9a3a7826de79ae61ef9ba46 100644
--- a/tests/libc/oracle/inttypes_h.5.res.oracle
+++ b/tests/libc/oracle/inttypes_h.5.res.oracle
@@ -1641,7 +1641,7 @@ int printf_va_54(char const * restrict format, int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_55(char const * restrict format, int *param0);
+int scanf_va_55(char const * restrict format, long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1654,7 +1654,7 @@ int scanf_va_55(char const * restrict format, int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_55(char const * restrict format, int param0);
+int printf_va_55(char const * restrict format, long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1671,7 +1671,7 @@ int printf_va_55(char const * restrict format, int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_56(char const * restrict format, int *param0);
+int scanf_va_56(char const * restrict format, long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1684,7 +1684,7 @@ int scanf_va_56(char const * restrict format, int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_56(char const * restrict format, int param0);
+int printf_va_56(char const * restrict format, long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1701,7 +1701,7 @@ int printf_va_56(char const * restrict format, int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_57(char const * restrict format, unsigned int *param0);
+int scanf_va_57(char const * restrict format, unsigned long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1714,7 +1714,7 @@ int scanf_va_57(char const * restrict format, unsigned int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_57(char const * restrict format, unsigned int param0);
+int printf_va_57(char const * restrict format, unsigned long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1731,7 +1731,7 @@ int printf_va_57(char const * restrict format, unsigned int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_58(char const * restrict format, unsigned int *param0);
+int scanf_va_58(char const * restrict format, unsigned long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1744,7 +1744,7 @@ int scanf_va_58(char const * restrict format, unsigned int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_58(char const * restrict format, unsigned int param0);
+int printf_va_58(char const * restrict format, unsigned long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1761,7 +1761,7 @@ int printf_va_58(char const * restrict format, unsigned int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_59(char const * restrict format, unsigned int *param0);
+int scanf_va_59(char const * restrict format, unsigned long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1774,7 +1774,7 @@ int scanf_va_59(char const * restrict format, unsigned int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_59(char const * restrict format, unsigned int param0);
+int printf_va_59(char const * restrict format, unsigned long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1791,7 +1791,7 @@ int printf_va_59(char const * restrict format, unsigned int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_60(char const * restrict format, unsigned int *param0);
+int scanf_va_60(char const * restrict format, unsigned long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1804,7 +1804,7 @@ int scanf_va_60(char const * restrict format, unsigned int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_60(char const * restrict format, unsigned int param0);
+int printf_va_60(char const * restrict format, unsigned long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1821,7 +1821,7 @@ int printf_va_60(char const * restrict format, unsigned int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_61(char const * restrict format, int *param0);
+int scanf_va_61(char const * restrict format, long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1834,7 +1834,7 @@ int scanf_va_61(char const * restrict format, int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_61(char const * restrict format, int param0);
+int printf_va_61(char const * restrict format, long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1851,7 +1851,7 @@ int printf_va_61(char const * restrict format, int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_62(char const * restrict format, int *param0);
+int scanf_va_62(char const * restrict format, long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1864,7 +1864,7 @@ int scanf_va_62(char const * restrict format, int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_62(char const * restrict format, int param0);
+int printf_va_62(char const * restrict format, long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1881,7 +1881,7 @@ int printf_va_62(char const * restrict format, int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_63(char const * restrict format, unsigned int *param0);
+int scanf_va_63(char const * restrict format, unsigned long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1894,7 +1894,7 @@ int scanf_va_63(char const * restrict format, unsigned int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_63(char const * restrict format, unsigned int param0);
+int printf_va_63(char const * restrict format, unsigned long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1911,7 +1911,7 @@ int printf_va_63(char const * restrict format, unsigned int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_64(char const * restrict format, unsigned int *param0);
+int scanf_va_64(char const * restrict format, unsigned long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1924,7 +1924,7 @@ int scanf_va_64(char const * restrict format, unsigned int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_64(char const * restrict format, unsigned int param0);
+int printf_va_64(char const * restrict format, unsigned long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1941,7 +1941,7 @@ int printf_va_64(char const * restrict format, unsigned int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_65(char const * restrict format, unsigned int *param0);
+int scanf_va_65(char const * restrict format, unsigned long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1954,7 +1954,7 @@ int scanf_va_65(char const * restrict format, unsigned int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_65(char const * restrict format, unsigned int param0);
+int printf_va_65(char const * restrict format, unsigned long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -1971,7 +1971,7 @@ int printf_va_65(char const * restrict format, unsigned int param0);
       \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data,
             (indirect: *(format + (0 ..)));
  */
-int scanf_va_66(char const * restrict format, unsigned int *param0);
+int scanf_va_66(char const * restrict format, unsigned long *param0);
 
 /*@ requires valid_read_string(format);
     assigns \result, __fc_stdout->__fc_FILE_data;
@@ -1984,7 +1984,7 @@ int scanf_va_66(char const * restrict format, unsigned int *param0);
             __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))),
             param0;
  */
-int printf_va_66(char const * restrict format, unsigned int param0);
+int printf_va_66(char const * restrict format, unsigned long param0);
 
 /*@ requires \valid(param0);
     requires valid_read_string(format);
@@ -2693,39 +2693,39 @@ int main(void)
   }
   {
     int_fast16_t x_17;
-    scanf("%d",& x_17); /* scanf_va_55 */
-    printf("%d",x_17); /* printf_va_55 */
-    scanf("%i",& x_17); /* scanf_va_56 */
-    printf("%i",x_17); /* printf_va_56 */
+    scanf("%ld",& x_17); /* scanf_va_55 */
+    printf("%ld",x_17); /* printf_va_55 */
+    scanf("%li",& x_17); /* scanf_va_56 */
+    printf("%li",x_17); /* printf_va_56 */
   }
   {
     uint_fast16_t x_18;
-    scanf("%o",& x_18); /* scanf_va_57 */
-    printf("%o",x_18); /* printf_va_57 */
-    scanf("%u",& x_18); /* scanf_va_58 */
-    printf("%u",x_18); /* printf_va_58 */
-    scanf("%x",& x_18); /* scanf_va_59 */
-    printf("%x",x_18); /* printf_va_59 */
-    scanf("%x",& x_18); /* scanf_va_60 */
-    printf("%X",x_18); /* printf_va_60 */
+    scanf("%lo",& x_18); /* scanf_va_57 */
+    printf("%lo",x_18); /* printf_va_57 */
+    scanf("%lu",& x_18); /* scanf_va_58 */
+    printf("%lu",x_18); /* printf_va_58 */
+    scanf("%lx",& x_18); /* scanf_va_59 */
+    printf("%lx",x_18); /* printf_va_59 */
+    scanf("%lx",& x_18); /* scanf_va_60 */
+    printf("%lX",x_18); /* printf_va_60 */
   }
   {
     int_fast32_t x_19;
-    scanf("%d",& x_19); /* scanf_va_61 */
-    printf("%d",x_19); /* printf_va_61 */
-    scanf("%i",& x_19); /* scanf_va_62 */
-    printf("%i",x_19); /* printf_va_62 */
+    scanf("%ld",& x_19); /* scanf_va_61 */
+    printf("%ld",x_19); /* printf_va_61 */
+    scanf("%li",& x_19); /* scanf_va_62 */
+    printf("%li",x_19); /* printf_va_62 */
   }
   {
     uint_fast32_t x_20;
-    scanf("%o",& x_20); /* scanf_va_63 */
-    printf("%o",x_20); /* printf_va_63 */
-    scanf("%u",& x_20); /* scanf_va_64 */
-    printf("%u",x_20); /* printf_va_64 */
-    scanf("%x",& x_20); /* scanf_va_65 */
-    printf("%x",x_20); /* printf_va_65 */
-    scanf("%x",& x_20); /* scanf_va_66 */
-    printf("%X",x_20); /* printf_va_66 */
+    scanf("%lo",& x_20); /* scanf_va_63 */
+    printf("%lo",x_20); /* printf_va_63 */
+    scanf("%lu",& x_20); /* scanf_va_64 */
+    printf("%lu",x_20); /* printf_va_64 */
+    scanf("%lx",& x_20); /* scanf_va_65 */
+    printf("%lx",x_20); /* printf_va_65 */
+    scanf("%lx",& x_20); /* scanf_va_66 */
+    printf("%lX",x_20); /* printf_va_66 */
   }
   {
     int_fast64_t x_21;
diff --git a/tests/libc/oracle/libgen_h.res.oracle b/tests/libc/oracle/libgen_h.res.oracle
index 2eeaf40c580c209ef0fd72c3720998b966ec0697..4d57e4b9a64827602fb28e5ea3f577c496d9e625 100644
--- a/tests/libc/oracle/libgen_h.res.oracle
+++ b/tests/libc/oracle/libgen_h.res.oracle
@@ -38,8 +38,8 @@
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
 [eva:final-states] Values at end of function main:
-  __fc_basename[0..255] ∈ [--..--]
-  __fc_dirname[0..255] ∈ [--..--]
+  __fc_basename[0..4095] ∈ [--..--]
+  __fc_dirname[0..4095] ∈ [--..--]
   path[0..127] ∈ [--..--]
   base ∈ {{ &__fc_basename[0] ; &path[0] }}
   base2 ∈ {{ NULL ; &__fc_basename[0] }}
diff --git a/tests/libc/oracle/limits_h.0.res.oracle b/tests/libc/oracle/limits_h.0.res.oracle
index 5efc6b677c12f12f339a65a77dd04ed411871a97..d42e459085a4be11eaabb8306061dd7af7309f38 100644
--- a/tests/libc/oracle/limits_h.0.res.oracle
+++ b/tests/libc/oracle/limits_h.0.res.oracle
@@ -4,9 +4,7 @@
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
   
-[eva] limits_h.c:16: assertion got status valid.
 [eva] limits_h.c:18: assertion got status valid.
-[eva] limits_h.c:19: assertion got status valid.
 [eva] limits_h.c:20: assertion got status valid.
 [eva] limits_h.c:21: assertion got status valid.
 [eva] limits_h.c:22: assertion got status valid.
@@ -26,13 +24,15 @@
 [eva] limits_h.c:36: assertion got status valid.
 [eva] limits_h.c:37: assertion got status valid.
 [eva] limits_h.c:38: assertion got status valid.
+[eva] limits_h.c:39: assertion got status valid.
+[eva] limits_h.c:40: assertion got status valid.
 [eva] Recording results for main
 [eva] done for function main
 [scope:rm_asserts] removing 6 assertion(s)
 [eva] ====== VALUES COMPUTED ======
 [eva:final-states] Values at end of function main:
   size_max ∈ {65535}
-  ssize_max ∈ {2147483647}
+  ssize_max ∈ {32767}
   intptr_max ∈ {2147483647}
   intptr_min ∈ {-2147483648}
   uintptr_max ∈ {4294967295}
diff --git a/tests/libc/oracle/limits_h.1.res.oracle b/tests/libc/oracle/limits_h.1.res.oracle
index 3affdff5cd178c4aaf8f9d2e55e081a1d36a3e60..d78a8936659922e423a02379a1a422f772c7bc8a 100644
--- a/tests/libc/oracle/limits_h.1.res.oracle
+++ b/tests/libc/oracle/limits_h.1.res.oracle
@@ -4,9 +4,7 @@
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
   
-[eva] limits_h.c:16: assertion got status valid.
 [eva] limits_h.c:18: assertion got status valid.
-[eva] limits_h.c:19: assertion got status valid.
 [eva] limits_h.c:20: assertion got status valid.
 [eva] limits_h.c:21: assertion got status valid.
 [eva] limits_h.c:22: assertion got status valid.
@@ -26,6 +24,8 @@
 [eva] limits_h.c:36: assertion got status valid.
 [eva] limits_h.c:37: assertion got status valid.
 [eva] limits_h.c:38: assertion got status valid.
+[eva] limits_h.c:39: assertion got status valid.
+[eva] limits_h.c:40: assertion got status valid.
 [eva] Recording results for main
 [eva] done for function main
 [scope:rm_asserts] removing 7 assertion(s)
diff --git a/tests/libc/oracle/limits_h.2.res.oracle b/tests/libc/oracle/limits_h.2.res.oracle
index f58b4f6de22cafe5371119260e1a015ec9f0f04d..f319e18684ca720670392c267aa897263718e6d4 100644
--- a/tests/libc/oracle/limits_h.2.res.oracle
+++ b/tests/libc/oracle/limits_h.2.res.oracle
@@ -4,9 +4,7 @@
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
   
-[eva] limits_h.c:16: assertion got status valid.
 [eva] limits_h.c:18: assertion got status valid.
-[eva] limits_h.c:19: assertion got status valid.
 [eva] limits_h.c:20: assertion got status valid.
 [eva] limits_h.c:21: assertion got status valid.
 [eva] limits_h.c:22: assertion got status valid.
@@ -26,6 +24,8 @@
 [eva] limits_h.c:36: assertion got status valid.
 [eva] limits_h.c:37: assertion got status valid.
 [eva] limits_h.c:38: assertion got status valid.
+[eva] limits_h.c:39: assertion got status valid.
+[eva] limits_h.c:40: assertion got status valid.
 [eva] Recording results for main
 [eva] done for function main
 [scope:rm_asserts] removing 7 assertion(s)
diff --git a/tests/libc/oracle/limits_h.3.res.oracle b/tests/libc/oracle/limits_h.3.res.oracle
index 5efc6b677c12f12f339a65a77dd04ed411871a97..d42e459085a4be11eaabb8306061dd7af7309f38 100644
--- a/tests/libc/oracle/limits_h.3.res.oracle
+++ b/tests/libc/oracle/limits_h.3.res.oracle
@@ -4,9 +4,7 @@
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
   
-[eva] limits_h.c:16: assertion got status valid.
 [eva] limits_h.c:18: assertion got status valid.
-[eva] limits_h.c:19: assertion got status valid.
 [eva] limits_h.c:20: assertion got status valid.
 [eva] limits_h.c:21: assertion got status valid.
 [eva] limits_h.c:22: assertion got status valid.
@@ -26,13 +24,15 @@
 [eva] limits_h.c:36: assertion got status valid.
 [eva] limits_h.c:37: assertion got status valid.
 [eva] limits_h.c:38: assertion got status valid.
+[eva] limits_h.c:39: assertion got status valid.
+[eva] limits_h.c:40: assertion got status valid.
 [eva] Recording results for main
 [eva] done for function main
 [scope:rm_asserts] removing 6 assertion(s)
 [eva] ====== VALUES COMPUTED ======
 [eva:final-states] Values at end of function main:
   size_max ∈ {65535}
-  ssize_max ∈ {2147483647}
+  ssize_max ∈ {32767}
   intptr_max ∈ {2147483647}
   intptr_min ∈ {-2147483648}
   uintptr_max ∈ {4294967295}
diff --git a/tests/libc/oracle/limits_h.4.res.oracle b/tests/libc/oracle/limits_h.4.res.oracle
index 3affdff5cd178c4aaf8f9d2e55e081a1d36a3e60..d78a8936659922e423a02379a1a422f772c7bc8a 100644
--- a/tests/libc/oracle/limits_h.4.res.oracle
+++ b/tests/libc/oracle/limits_h.4.res.oracle
@@ -4,9 +4,7 @@
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
   
-[eva] limits_h.c:16: assertion got status valid.
 [eva] limits_h.c:18: assertion got status valid.
-[eva] limits_h.c:19: assertion got status valid.
 [eva] limits_h.c:20: assertion got status valid.
 [eva] limits_h.c:21: assertion got status valid.
 [eva] limits_h.c:22: assertion got status valid.
@@ -26,6 +24,8 @@
 [eva] limits_h.c:36: assertion got status valid.
 [eva] limits_h.c:37: assertion got status valid.
 [eva] limits_h.c:38: assertion got status valid.
+[eva] limits_h.c:39: assertion got status valid.
+[eva] limits_h.c:40: assertion got status valid.
 [eva] Recording results for main
 [eva] done for function main
 [scope:rm_asserts] removing 7 assertion(s)
diff --git a/tests/libc/oracle/limits_h.5.res.oracle b/tests/libc/oracle/limits_h.5.res.oracle
index f58b4f6de22cafe5371119260e1a015ec9f0f04d..f319e18684ca720670392c267aa897263718e6d4 100644
--- a/tests/libc/oracle/limits_h.5.res.oracle
+++ b/tests/libc/oracle/limits_h.5.res.oracle
@@ -4,9 +4,7 @@
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
   
-[eva] limits_h.c:16: assertion got status valid.
 [eva] limits_h.c:18: assertion got status valid.
-[eva] limits_h.c:19: assertion got status valid.
 [eva] limits_h.c:20: assertion got status valid.
 [eva] limits_h.c:21: assertion got status valid.
 [eva] limits_h.c:22: assertion got status valid.
@@ -26,6 +24,8 @@
 [eva] limits_h.c:36: assertion got status valid.
 [eva] limits_h.c:37: assertion got status valid.
 [eva] limits_h.c:38: assertion got status valid.
+[eva] limits_h.c:39: assertion got status valid.
+[eva] limits_h.c:40: assertion got status valid.
 [eva] Recording results for main
 [eva] done for function main
 [scope:rm_asserts] removing 7 assertion(s)
diff --git a/tests/libc/oracle/limits_h.6.res.oracle b/tests/libc/oracle/limits_h.6.res.oracle
index 3affdff5cd178c4aaf8f9d2e55e081a1d36a3e60..d78a8936659922e423a02379a1a422f772c7bc8a 100644
--- a/tests/libc/oracle/limits_h.6.res.oracle
+++ b/tests/libc/oracle/limits_h.6.res.oracle
@@ -4,9 +4,7 @@
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
   
-[eva] limits_h.c:16: assertion got status valid.
 [eva] limits_h.c:18: assertion got status valid.
-[eva] limits_h.c:19: assertion got status valid.
 [eva] limits_h.c:20: assertion got status valid.
 [eva] limits_h.c:21: assertion got status valid.
 [eva] limits_h.c:22: assertion got status valid.
@@ -26,6 +24,8 @@
 [eva] limits_h.c:36: assertion got status valid.
 [eva] limits_h.c:37: assertion got status valid.
 [eva] limits_h.c:38: assertion got status valid.
+[eva] limits_h.c:39: assertion got status valid.
+[eva] limits_h.c:40: assertion got status valid.
 [eva] Recording results for main
 [eva] done for function main
 [scope:rm_asserts] removing 7 assertion(s)
diff --git a/tests/libc/oracle/limits_h.7.res.oracle b/tests/libc/oracle/limits_h.7.res.oracle
index c5ca9b76a1d60e30ad18a2156d760d0487b2628c..5cd6ee11b6548aa5c94a7d21ff596a60ece19dbc 100644
--- a/tests/libc/oracle/limits_h.7.res.oracle
+++ b/tests/libc/oracle/limits_h.7.res.oracle
@@ -4,9 +4,7 @@
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
   
-[eva] limits_h.c:16: assertion got status valid.
 [eva] limits_h.c:18: assertion got status valid.
-[eva] limits_h.c:19: assertion got status valid.
 [eva] limits_h.c:20: assertion got status valid.
 [eva] limits_h.c:21: assertion got status valid.
 [eva] limits_h.c:22: assertion got status valid.
@@ -26,6 +24,8 @@
 [eva] limits_h.c:36: assertion got status valid.
 [eva] limits_h.c:37: assertion got status valid.
 [eva] limits_h.c:38: assertion got status valid.
+[eva] limits_h.c:39: assertion got status valid.
+[eva] limits_h.c:40: assertion got status valid.
 [eva] Recording results for main
 [eva] done for function main
 [scope:rm_asserts] removing 7 assertion(s)
diff --git a/tests/libc/oracle/limits_h.8.res.oracle b/tests/libc/oracle/limits_h.8.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..01d45df1542894c909d0b1598daad6f65f3e79f0
--- /dev/null
+++ b/tests/libc/oracle/limits_h.8.res.oracle
@@ -0,0 +1,38 @@
+[kernel] Parsing limits_h.c (with preprocessing)
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  
+[eva] limits_h.c:18: assertion got status valid.
+[eva] limits_h.c:20: assertion got status valid.
+[eva] limits_h.c:21: assertion got status valid.
+[eva] limits_h.c:22: assertion got status valid.
+[eva] limits_h.c:23: assertion got status valid.
+[eva] limits_h.c:24: assertion got status valid.
+[eva] limits_h.c:25: assertion got status valid.
+[eva] limits_h.c:26: assertion got status valid.
+[eva] limits_h.c:27: assertion got status valid.
+[eva] limits_h.c:28: assertion got status valid.
+[eva] limits_h.c:29: assertion got status valid.
+[eva] limits_h.c:30: assertion got status valid.
+[eva] limits_h.c:31: assertion got status valid.
+[eva] limits_h.c:32: assertion got status valid.
+[eva] limits_h.c:33: assertion got status valid.
+[eva] limits_h.c:34: assertion got status valid.
+[eva] limits_h.c:35: assertion got status valid.
+[eva] limits_h.c:36: assertion got status valid.
+[eva] limits_h.c:37: assertion got status valid.
+[eva] limits_h.c:38: assertion got status valid.
+[eva] limits_h.c:39: assertion got status valid.
+[eva] limits_h.c:40: assertion got status valid.
+[eva] Recording results for main
+[eva] done for function main
+[scope:rm_asserts] removing 6 assertion(s)
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function main:
+  size_max ∈ {65535}
+  intptr_max ∈ {32767}
+  intptr_min ∈ {-32768}
+  uintptr_max ∈ {65535}
+  uintmax_max ∈ {18446744073709551615}
diff --git a/tests/libc/oracle/limits_h.9.res.oracle b/tests/libc/oracle/limits_h.9.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..01d45df1542894c909d0b1598daad6f65f3e79f0
--- /dev/null
+++ b/tests/libc/oracle/limits_h.9.res.oracle
@@ -0,0 +1,38 @@
+[kernel] Parsing limits_h.c (with preprocessing)
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  
+[eva] limits_h.c:18: assertion got status valid.
+[eva] limits_h.c:20: assertion got status valid.
+[eva] limits_h.c:21: assertion got status valid.
+[eva] limits_h.c:22: assertion got status valid.
+[eva] limits_h.c:23: assertion got status valid.
+[eva] limits_h.c:24: assertion got status valid.
+[eva] limits_h.c:25: assertion got status valid.
+[eva] limits_h.c:26: assertion got status valid.
+[eva] limits_h.c:27: assertion got status valid.
+[eva] limits_h.c:28: assertion got status valid.
+[eva] limits_h.c:29: assertion got status valid.
+[eva] limits_h.c:30: assertion got status valid.
+[eva] limits_h.c:31: assertion got status valid.
+[eva] limits_h.c:32: assertion got status valid.
+[eva] limits_h.c:33: assertion got status valid.
+[eva] limits_h.c:34: assertion got status valid.
+[eva] limits_h.c:35: assertion got status valid.
+[eva] limits_h.c:36: assertion got status valid.
+[eva] limits_h.c:37: assertion got status valid.
+[eva] limits_h.c:38: assertion got status valid.
+[eva] limits_h.c:39: assertion got status valid.
+[eva] limits_h.c:40: assertion got status valid.
+[eva] Recording results for main
+[eva] done for function main
+[scope:rm_asserts] removing 6 assertion(s)
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function main:
+  size_max ∈ {65535}
+  intptr_max ∈ {32767}
+  intptr_min ∈ {-32768}
+  uintptr_max ∈ {65535}
+  uintmax_max ∈ {18446744073709551615}
diff --git a/tests/libc/oracle/signal_h.res.oracle b/tests/libc/oracle/signal_h.res.oracle
index 7c70744fb716464287f0a4115e9fc8b0831f7884..efade1922a061ad31e4bdcaa1ff5ad0f22ace360 100644
--- a/tests/libc/oracle/signal_h.res.oracle
+++ b/tests/libc/oracle/signal_h.res.oracle
@@ -126,7 +126,7 @@
   function sigaction: precondition 'valid_read_act_or_null' got status valid.
 [eva] signal_h.c:48: 
   function sigaction: precondition 'separation,separated_acts' got status valid.
-[eva] FRAMAC_SHARE/libc/signal.h:223: 
+[eva] FRAMAC_SHARE/libc/signal.h:229: 
   cannot evaluate ACSL term, unsupported ACSL construct: logic coercion struct sigaction -> set<struct sigaction>
 [eva] Done for function sigaction
 [eva] computing for function sigaction <- main.
diff --git a/tests/libc/oracle/stdlib_c.0.res.oracle b/tests/libc/oracle/stdlib_c.0.res.oracle
index cb22bbb0198fb86def1f95ae8ab4817a07775f8c..276e662d50c399250dce2614e96308566c68c36b 100644
--- a/tests/libc/oracle/stdlib_c.0.res.oracle
+++ b/tests/libc/oracle/stdlib_c.0.res.oracle
@@ -256,21 +256,21 @@
   resolved_name ∈
                {{ NULL ; &__malloc_main_l44[0] ; &__malloc_realpath_l224[0] ;
                   &__malloc_realpath_l224_0[0] }}
-  realpath_len ∈ [1..256]
+  realpath_len ∈ [1..4096]
   __retres ∈
           {{ NULL ; &__malloc_main_l44[0] ; &__malloc_realpath_l224[0] ;
              &__malloc_realpath_l224_0[0] }}
-  __malloc_main_l44[0..255] ∈ [--..--] or UNINITIALIZED
+  __malloc_main_l44[0..4095] ∈ [--..--] or UNINITIALIZED
   __malloc_realpath_l224[0] ∈ [--..--]
-                        [1..255] ∈ [--..--] or UNINITIALIZED
+                        [1..4095] ∈ [--..--] or UNINITIALIZED
   __malloc_realpath_l224_0[0] ∈ [--..--]
-                          [1..255] ∈ [--..--] or UNINITIALIZED
+                          [1..4095] ∈ [--..--] or UNINITIALIZED
 [eva:final-states] Values at end of function canonicalize_file_name:
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_errno ∈ [--..--]
   __malloc_realpath_l224_0[0] ∈ [--..--]
-                          [1..255] ∈ [--..--] or UNINITIALIZED
+                          [1..4095] ∈ [--..--] or UNINITIALIZED
 [eva:final-states] Values at end of function main:
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
@@ -289,8 +289,8 @@
   canon ∈ {{ NULL ; &__malloc_realpath_l224_0[0] }}
   __retres ∈ {0; 1}
   __calloc_w_main_l33[0..1073741823] ∈ {0; 42}
-  __malloc_main_l44[0..255] ∈ [--..--] or UNINITIALIZED
+  __malloc_main_l44[0..4095] ∈ [--..--] or UNINITIALIZED
   __malloc_realpath_l224[0] ∈ [--..--]
-                        [1..255] ∈ [--..--] or UNINITIALIZED
+                        [1..4095] ∈ [--..--] or UNINITIALIZED
   __malloc_realpath_l224_0[0] ∈ [--..--]
-                          [1..255] ∈ [--..--] or UNINITIALIZED
+                          [1..4095] ∈ [--..--] or UNINITIALIZED
diff --git a/tests/libc/oracle/stdlib_c.1.res.oracle b/tests/libc/oracle/stdlib_c.1.res.oracle
index 96a5d173a353310558116dac6f02425b4a3d3b39..95a6a6d6b063be4bf82b8f17affcbf3e9e09f9fe 100644
--- a/tests/libc/oracle/stdlib_c.1.res.oracle
+++ b/tests/libc/oracle/stdlib_c.1.res.oracle
@@ -274,21 +274,21 @@
   resolved_name ∈
                {{ NULL ; &__malloc_main_l44[0] ; &__malloc_realpath_l224[0] ;
                   &__malloc_realpath_l224_0[0] }}
-  realpath_len ∈ [1..256]
+  realpath_len ∈ [1..4096]
   __retres ∈
           {{ NULL ; &__malloc_main_l44[0] ; &__malloc_realpath_l224[0] ;
              &__malloc_realpath_l224_0[0] }}
-  __malloc_main_l44[0..255] ∈ [--..--] or UNINITIALIZED
+  __malloc_main_l44[0..4095] ∈ [--..--] or UNINITIALIZED
   __malloc_realpath_l224[0] ∈ [--..--]
-                        [1..255] ∈ [--..--] or UNINITIALIZED
+                        [1..4095] ∈ [--..--] or UNINITIALIZED
   __malloc_realpath_l224_0[0] ∈ [--..--]
-                          [1..255] ∈ [--..--] or UNINITIALIZED
+                          [1..4095] ∈ [--..--] or UNINITIALIZED
 [eva:final-states] Values at end of function canonicalize_file_name:
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_errno ∈ [--..--]
   __malloc_realpath_l224_0[0] ∈ [--..--]
-                          [1..255] ∈ [--..--] or UNINITIALIZED
+                          [1..4095] ∈ [--..--] or UNINITIALIZED
 [eva:final-states] Values at end of function main:
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
@@ -307,8 +307,8 @@
   canon ∈ {{ NULL ; &__malloc_realpath_l224_0[0] }}
   __retres ∈ {0}
   __calloc_w_main_l33[0..1073741823] ∈ {0; 42}
-  __malloc_main_l44[0..255] ∈ [--..--] or UNINITIALIZED
+  __malloc_main_l44[0..4095] ∈ [--..--] or UNINITIALIZED
   __malloc_realpath_l224[0] ∈ [--..--]
-                        [1..255] ∈ [--..--] or UNINITIALIZED
+                        [1..4095] ∈ [--..--] or UNINITIALIZED
   __malloc_realpath_l224_0[0] ∈ [--..--]
-                          [1..255] ∈ [--..--] or UNINITIALIZED
+                          [1..4095] ∈ [--..--] or UNINITIALIZED
diff --git a/tests/libc/oracle/stdlib_c.2.res.oracle b/tests/libc/oracle/stdlib_c.2.res.oracle
index ff5db5635efaa67de7c7c6da5d9953b25c86a9c4..8090933af98958cc3fd154206444496df7d62a26 100644
--- a/tests/libc/oracle/stdlib_c.2.res.oracle
+++ b/tests/libc/oracle/stdlib_c.2.res.oracle
@@ -228,18 +228,18 @@
   resolved_name ∈
                {{ NULL ; &__malloc_main_l44[0] ; &__malloc_realpath_l224[0] ;
                   &__malloc_realpath_l224_0[0] }}
-  realpath_len ∈ [1..256]
+  realpath_len ∈ [1..4096]
   __retres ∈
           {{ NULL ; &__malloc_main_l44[0] ; &__malloc_realpath_l224[0] ;
              &__malloc_realpath_l224_0[0] }}
-  __malloc_main_l44[0..255] ∈ [--..--] or UNINITIALIZED
-  __malloc_realpath_l224[0..255] ∈ [--..--] or UNINITIALIZED
-  __malloc_realpath_l224_0[0..255] ∈ [--..--] or UNINITIALIZED
+  __malloc_main_l44[0..4095] ∈ [--..--] or UNINITIALIZED
+  __malloc_realpath_l224[0..4095] ∈ [--..--] or UNINITIALIZED
+  __malloc_realpath_l224_0[0..4095] ∈ [--..--] or UNINITIALIZED
 [eva:final-states] Values at end of function canonicalize_file_name:
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
   __fc_errno ∈ [--..--]
-  __malloc_realpath_l224_0[0..255] ∈ [--..--] or UNINITIALIZED
+  __malloc_realpath_l224_0[0..4095] ∈ [--..--] or UNINITIALIZED
 [eva:final-states] Values at end of function main:
   __fc_heap_status ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
@@ -260,6 +260,6 @@
   __malloc_calloc_l72[0..3] ∈ [--..--] or UNINITIALIZED
   __malloc_calloc_l72_0[0..4294967291] ∈ [--..--] or UNINITIALIZED
   __malloc_w_calloc_l72_1[0..4294967291] ∈ [--..--] or UNINITIALIZED
-  __malloc_main_l44[0..255] ∈ [--..--] or UNINITIALIZED
-  __malloc_realpath_l224[0..255] ∈ [--..--] or UNINITIALIZED
-  __malloc_realpath_l224_0[0..255] ∈ [--..--] or UNINITIALIZED
+  __malloc_main_l44[0..4095] ∈ [--..--] or UNINITIALIZED
+  __malloc_realpath_l224[0..4095] ∈ [--..--] or UNINITIALIZED
+  __malloc_realpath_l224_0[0..4095] ∈ [--..--] or UNINITIALIZED
diff --git a/tests/libc/runtime.c b/tests/libc/runtime.c
index ec7f02cf510f4293be5c1215a9fc6d403eae49ef..25588a82e04f0833265e745ac70217161f1b0ef7 100644
--- a/tests/libc/runtime.c
+++ b/tests/libc/runtime.c
@@ -1,7 +1,7 @@
 /* run.config*
    COMMENT: tests that the runtime can compile without errors (for PathCrawler, E-ACSL, ...)
-   CMD: gcc -D__FC_MACHDEP_X86_64 @FRAMAC_SHARE@/libc/__fc_runtime.c -Wno-attributes -std=c99 -Wall -Wwrite-strings -o @DEV_NULL@
-   OPT:
+   CMD: FRAMAC='@frama-c@' %{dep:@PTEST_DIR@/runtime.sh}
+   OPT: %{dep:@FRAMAC_SHARE@/libc/__fc_runtime.c}
  */
 
 int main() {
diff --git a/tests/libc/runtime.sh b/tests/libc/runtime.sh
new file mode 100755
index 0000000000000000000000000000000000000000..aee0cf3d823f1aa61f34db70db8fd8caae2f4239
--- /dev/null
+++ b/tests/libc/runtime.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+set -e
+if test -z "$FRAMAC"; then echo "variable FRAMAC must be set"; exit 1; fi
+TMPDIR=$(mktemp -d fc_test_libc_XXXXXXXX)
+$FRAMAC -print-machdep-header > $TMPDIR/__fc_machdep.h
+gcc -I$TMPDIR -D__FC_MACHDEP_X86_64 $@ -Wno-attributes -std=c99 -Wall -Wwrite-strings -o /dev/null
+rm -fr $TMPDIR
diff --git a/tests/misc/add_assigns.ml b/tests/misc/add_assigns.ml
index 11df28607ac8e92edffb3d1ef12b31e1b4f8440d..04d7bec1b147135f8b102a33365da9196a1c918f 100644
--- a/tests/misc/add_assigns.ml
+++ b/tests/misc/add_assigns.ml
@@ -11,7 +11,7 @@ let main () =
     computed := true;
     Ast.compute ();
     let kf = Globals.Functions.find_by_name "f" in
-    let y = Globals.Vars.find_from_astinfo "y" (VFormal kf) in
+    let y = Globals.Vars.find_from_astinfo "y" (Formal kf) in
     let mem =
       Logic_const.(
         new_identified_term
diff --git a/tests/misc/custom_machdep.c b/tests/misc/custom_machdep.c
index c51544e41f4e98bea09bda86ebeb580a1c6db8b8..1152d590191677fbcd9ca7a88afa65f5d71aa6b3 100644
--- a/tests/misc/custom_machdep.c
+++ b/tests/misc/custom_machdep.c
@@ -1,11 +1,6 @@
 /* run.config*
- EXIT: 1
- MODULE: @PTEST_NAME@.cmxs
- DEPS: @PTEST_NAME@/__fc_machdep_custom.h
-   OPT: -cpp-extra-args="-I./@PTEST_NAME@ -D__FC_MACHDEP_CUSTOM" -machdep custom -print -then -print
-  COMMENT: we need a -then to test double registering of a machdep
+ OPT: -machdep %{dep:@PTEST_DIR@/@PTEST_NAME@.yaml} -print
 */
-#include "__fc_machdep_custom.h"
 // most of the following includes are not directly used, but they test if
 // the custom machdep has defined the necessary constants
 #include <ctype.h>
@@ -22,4 +17,4 @@
 #include <time.h>
 #include <wchar.h>
 
-int main() { return INT_MAX; }
+int main() { return INT_MAX - CUSTOM_MACHDEP; }
diff --git a/tests/misc/custom_machdep.ml b/tests/misc/custom_machdep.ml
deleted file mode 100644
index 503611ae1fec6f6b921e2d1cdeecfeae7fba075b..0000000000000000000000000000000000000000
--- a/tests/misc/custom_machdep.ml
+++ /dev/null
@@ -1,57 +0,0 @@
-open Cil_types
-
-let mach =
-  {
-    version          = "foo";
-    compiler         = "bar";
-    cpp_arch_flags   = [];
-    sizeof_short     = 2;
-    sizeof_int       = 3;
-    sizeof_long      = 4;
-    sizeof_longlong  = 8;
-    sizeof_ptr       = 4;
-    sizeof_float     = 4;
-    sizeof_double    = 8;
-    sizeof_longdouble  = 12;
-    sizeof_void      = 1;
-    sizeof_fun       = 1;
-    size_t = "unsigned long";
-    wchar_t = "int";
-    ptrdiff_t = "int";
-    alignof_short = 2;
-    alignof_int = 3;
-    alignof_long = 4;
-    alignof_longlong = 4;
-    alignof_ptr = 4;
-    alignof_float = 4;
-    alignof_double = 4;
-    alignof_longdouble = 4;
-    alignof_str = 1;
-    alignof_fun = 1;
-    alignof_aligned= 16;
-    char_is_unsigned = false;
-    const_string_literals = true;
-    little_endian = true;
-    underscore_name = false ;
-    has__builtin_va_list = true;
-  }
-
-let mach2 = { mach with compiler = "baz" }
-
-(* First run : register [mach] under name [custom].
-   Second run :
-   - register [mach] under name [custom] again. This must work.
-   - then register [mach2] under name [custom]. This must result in an error.
-*)
-let () =
-  let ran = ref false in
-  Cmdline.run_after_loading_stage
-    (fun () ->
-       Kernel.result "Registering machdep 'mach' as 'custom'";
-       File.new_machdep "custom" mach;
-       if !ran then begin
-         Kernel.result "Trying to register machdep 'mach2' as 'custom'";
-         File.new_machdep "custom" mach2
-       end
-       else ran := true
-    )
diff --git a/tests/misc/custom_machdep.yaml b/tests/misc/custom_machdep.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7872b93e4ddd025199dbcedd0a868d908bc8909a
--- /dev/null
+++ b/tests/misc/custom_machdep.yaml
@@ -0,0 +1,80 @@
+alignof_aligned: 16
+alignof_double: 4
+alignof_float: 4
+alignof_fun: 1
+alignof_int: 3
+alignof_long: 4
+alignof_longdouble: 4
+alignof_longlong: 4
+alignof_ptr: 4
+alignof_short: 2
+alignof_str: 1
+char_is_unsigned: false
+compiler: bar
+cpp_arch_flags: []
+has__builtin_va_list: true
+little_endian: true
+ptrdiff_t: int
+intptr_t: long
+uintptr_t: unsigned long
+int_fast8_t: signed char
+int_fast16_t: long
+int_fast32_t: long
+int_fast64_t: long long
+uint_fast8_t: unsigned char
+uint_fast16_t: unsigned long
+uint_fast32_t: unsigned long
+uint_fast64_t: unsigned long long
+wint_t: int
+size_t: unsigned long
+sizeof_double: 8
+sizeof_float: 4
+sizeof_fun: 1
+sizeof_int: 3
+sizeof_long: 4
+sizeof_longdouble: 12
+sizeof_longlong: 8
+sizeof_ptr: 4
+sizeof_short: 2
+sizeof_void: 1
+ssize_t: long
+version: foo
+wchar_t: int
+weof: (-1)
+wordsize: '24'
+posix_version: '200809L'
+bufsiz: '255'
+eof: (-1)
+fopen_max: '128'
+filename_max: '1023'
+l_tmpnam: '255'
+tmp_max: '255'
+tty_name_max: '255'
+host_name_max: '255'
+path_max: '256'
+rand_max: '0xFFFFFE'
+mb_cur_max: '16'
+sig_atomic_t: int
+time_t: long
+nsig: ''
+errno:
+  edom: "33"
+  eilseq: "84"
+  erange: "34"
+  eintr: "35"
+  eagain: "36"
+  ebadf: "37"
+  efbig: "38"
+  einval: "39"
+  eio: "40"
+  enospc: "41"
+  eoverflow: "42"
+  epipe: "43"
+  espipe: "44"
+  enxio: "45"
+  emfile: "46"
+  enomem: "47"
+  enotsup: "48"
+machdep_name: custom_machdep
+custom_defs: |
+  #define CUSTOM_MACHDEP 1
diff --git a/tests/misc/custom_machdep/__fc_machdep_custom.h b/tests/misc/custom_machdep/__fc_machdep_custom.h
deleted file mode 100644
index 27db308403368e394b64d739b9ac7e2c9699f936..0000000000000000000000000000000000000000
--- a/tests/misc/custom_machdep/__fc_machdep_custom.h
+++ /dev/null
@@ -1,243 +0,0 @@
-/* skeleton of a real custom machdep header.
-   Note: the values provided here are merely for illustrative purposes
-         and are not necessarily consistent between them. */
-#ifndef __FC_MACHDEP
-#define __FC_MACHDEP
-
-#ifdef __FC_MACHDEP_CUSTOM
-
-/* Constants required by the C standard */
-#undef  __CHAR_UNSIGNED__
-#define __WORDSIZE 32
-#define __SIZEOF_SHORT 2
-#define __SIZEOF_INT 3
-#define __SIZEOF_LONG 4
-#define __SIZEOF_LONGLONG 8
-#define __CHAR_BIT 8
-#define __PTRDIFF_T int
-#define __SIZE_T unsigned int
-
-#define __FC_SCHAR_MIN (-128)
-#define __FC_SCHAR_MAX 127
-#define __FC_UCHAR_MAX 255
-#define __FC_SHRT_MIN (-32768)
-#define __FC_SHRT_MAX 32767
-#define __FC_USHRT_MAX 65535
-#define __FC_INT_MIN (-2147483647 - 1)
-#define __FC_INT_MAX 2147483647
-#define __FC_UINT_MAX 4294967295U
-#define __FC_LONG_MIN (-2147483647L -1L)
-#define __FC_LONG_MAX 2147483647L
-#define __FC_ULONG_MAX 4294967295UL
-#define __FC_LLONG_MIN (-9223372036854775807LL -1LL)
-#define __FC_LLONG_MAX 9223372036854775807LL
-#define __FC_ULLONG_MAX 18446744073709551615ULL
-
-#define __INT_MAX_T signed long long
-#define __UINT_MAX_T unsigned long long
-
-#define __FC_PATH_MAX 256
-#define __FC_SIZE_MAX __FC_ULLONG_MAX
-
-/* Optional constants */
-#define __INT8_T signed char
-#define __UINT8_T unsigned char
-#define __INT16_T signed short
-#define __UINT16_T unsigned short
-
-#define __INTPTR_T signed long
-#define __UINTPTR_T unsigned long
-#define __INT32_T signed long
-#define __UINT32_T unsigned long
-#define __INT64_T signed long long
-#define __UINT64_T unsigned long long
-
-/* Required constants */
-#define __INT_LEAST8_T signed char
-#define __UINT_LEAST8_T unsigned char
-#define __INT_LEAST16_T signed short
-#define __UINT_LEAST16_T unsigned short
-#define __INT_LEAST32_T signed long
-#define __UINT_LEAST32_T unsigned long
-#define __INT_LEAST64_T signed long long
-#define __UINT_LEAST64_T unsigned long long
-
-#define __INT_FAST8_T signed char
-#define __UINT_FAST8_T unsigned char
-#define __INT_FAST16_T signed int
-#define __UINT_FAST16_T unsigned int
-#define __INT_FAST32_T signed long
-#define __UINT_FAST32_T unsigned long
-#define __INT_FAST64_T signed long long
-#define __UINT_FAST64_T unsigned long long
-
-
-/* POSIX */
-#define __SSIZE_T int
-/* stdio.h */
-#define __FC_L_tmpnam 1024
-/* stdint.h */
-#define __FC_PTRDIFF_MIN __FC_INT_MIN
-#define __FC_PTRDIFF_MAX __FC_INT_MAX
-#define __FC_INTMAX_MIN (-9223372036854775807LL -1LL)
-#define __FC_INTMAX_MAX 9223372036854775807LL
-#define __FC_UINTMAX_MAX 18446744073709551615ULL
-
-#define __FC_EOF (-1)
-#define __FC_FOPEN_MAX 20
-#define __FC_RAND_MAX 32767
-#define __WCHAR_T unsigned short
-
-/* for stdarg.h */
-#define __FC_VA_LIST_T char*
-
-/* for time.h */
-#define __FC_TIME_T long
-
-/* for wchar.h */
-#define __WINT_T unsigned int
-#define __FC_WEOF (0xFFFFFFFFU)
-#define __FC_WINT_MIN 0
-#define __FC_WINT_MAX __FC_UINT_MAX
-
-/* for errno.h */
-
-#define __FC_EPERM 1
-#define __FC_ENOENT 2
-#define __FC_ESRCH 3
-#define __FC_EINTR 4
-#define __FC_EIO 5
-#define __FC_ENXIO 6
-#define __FC_E2BIG 7
-#define __FC_ENOEXEC 8
-#define __FC_EBADF 9
-#define __FC_ECHILD 10
-#define __FC_EAGAIN 11
-#define __FC_ENOMEM 12
-#define __FC_EACCES 13
-#define __FC_EFAULT 14
-#define __FC_ENOTBLK 15
-#define __FC_EBUSY 16
-#define __FC_EEXIST 17
-#define __FC_EXDEV 18
-#define __FC_ENODEV 19
-#define __FC_ENOTDIR 20
-#define __FC_EISDIR 21
-#define __FC_EINVAL 22
-#define __FC_ENFILE 23
-#define __FC_EMFILE 24
-#define __FC_ENOTTY 25
-#define __FC_ETXTBSY 26
-#define __FC_EFBIG 27
-#define __FC_ENOSPC 28
-#define __FC_ESPIPE 29
-#define __FC_EROFS 30
-#define __FC_EMLINK 31
-#define __FC_EPIPE 32
-#define __FC_EDOM 33
-#define __FC_ERANGE 34
-#define __FC_EDEADLK 35
-#define __FC_ENAMETOOLONG 36
-#define __FC_ENOLCK 37
-#define __FC_ENOSYS 38
-#define __FC_ENOTEMPTY 39
-#define __FC_ELOOP 40
-#define __FC_EWOULDBLOCK EAGAIN
-#define __FC_ENOMSG 42
-#define __FC_EIDRM 43
-#define __FC_ECHRNG 44
-#define __FC_EL2NSYNC 45
-#define __FC_EL3HLT 46
-#define __FC_EL3RST 47
-#define __FC_ELNRNG 48
-#define __FC_EUNATCH 49
-#define __FC_ENOCSI 50
-#define __FC_EL2HLT 51
-#define __FC_EBADE 52
-#define __FC_EBADR 53
-#define __FC_EXFULL 54
-#define __FC_ENOANO 55
-#define __FC_EBADRQC 56
-#define __FC_EBADSLT 57
-#define __FC_EDEADLOCK EDEADLK
-#define __FC_EBFONT 59
-#define __FC_ENOSTR 60
-#define __FC_ENODATA 61
-#define __FC_ETIME 62
-#define __FC_ENOSR 63
-#define __FC_ENONET 64
-#define __FC_ENOPKG 65
-#define __FC_EREMOTE 66
-#define __FC_ENOLINK 67
-#define __FC_EADV 68
-#define __FC_ESRMNT 69
-#define __FC_ECOMM 70
-#define __FC_EPROTO 71
-#define __FC_EMULTIHOP 72
-#define __FC_EDOTDOT 73
-#define __FC_EBADMSG 74
-#define __FC_EOVERFLOW 75
-#define __FC_ENOTUNIQ 76
-#define __FC_EBADFD 77
-#define __FC_EREMCHG 78
-#define __FC_ELIBACC 79
-#define __FC_ELIBBAD 80
-#define __FC_ELIBSCN 81
-#define __FC_ELIBMAX 82
-#define __FC_ELIBEXEC 83
-#define __FC_EILSEQ 84
-#define __FC_ERESTART 85
-#define __FC_ESTRPIPE 86
-#define __FC_EUSERS 87
-#define __FC_ENOTSOCK 88
-#define __FC_EDESTADDRREQ 89
-#define __FC_EMSGSIZE 90
-#define __FC_EPROTOTYPE 91
-#define __FC_ENOPROTOOPT 92
-#define __FC_EPROTONOSUPPORT 93
-#define __FC_ESOCKTNOSUPPORT 94
-#define __FC_ENOTSUP 95
-#define __FC_EOPNOTSUPP 95
-#define __FC_EPFNOSUPPORT 96
-#define __FC_EAFNOSUPPORT 97
-#define __FC_EADDRINUSE 98
-#define __FC_EADDRNOTAVAIL 99
-#define __FC_ENETDOWN 100
-#define __FC_ENETUNREACH 101
-#define __FC_ENETRESET 102
-#define __FC_ECONNABORTED 103
-#define __FC_ECONNRESET 104
-#define __FC_ENOBUFS 105
-#define __FC_EISCONN 106
-#define __FC_ENOTCONN 107
-#define __FC_ESHUTDOWN 108
-#define __FC_ETOOMANYREFS 109
-#define __FC_ETIMEDOUT 110
-#define __FC_ECONNREFUSED 111
-#define __FC_EHOSTDOWN 112
-#define __FC_EHOSTUNREACH 113
-#define __FC_EALREADY 114
-#define __FC_EINPROGRESS 115
-#define __FC_ESTALE 116
-#define __FC_EUCLEAN 117
-#define __FC_ENOTNAM 118
-#define __FC_ENAVAIL 119
-#define __FC_EISNAM 120
-#define __FC_EREMOTEIO 121
-#define __FC_EDQUOT 122
-#define __FC_ENOMEDIUM 123
-#define __FC_EMEDIUMTYPE 124
-#define __FC_ECANCELED 125
-#define __FC_ENOKEY 126
-#define __FC_EKEYEXPIRED 127
-#define __FC_EKEYREVOKED 128
-#define __FC_EKEYREJECTED 129
-#define __FC_EOWNERDEAD 130
-#define __FC_ENOTRECOVERABLE 131
-#define __FC_ERFKILL 132
-#define __FC_EHWPOISON 133
-
-#else
-  error "I'm supposed to be called with __FC_MACHDEP_CUSTOM macro defined"
-#endif
-#endif
diff --git a/tests/misc/dune b/tests/misc/dune
deleted file mode 100644
index 350ae7160b3c799e3d13271dd4342fb7e90279c8..0000000000000000000000000000000000000000
--- a/tests/misc/dune
+++ /dev/null
@@ -1,3 +0,0 @@
-(subdir
- result/custom_machdep
- (copy_files ../../custom_machdep/*))
diff --git a/tests/misc/oracle/custom_machdep.res.oracle b/tests/misc/oracle/custom_machdep.res.oracle
index dfa8454076f143b1f9a7fd8f5d71a56519f74ab5..85375c33f5000a97731ffc41e079abbdfb50a323 100644
--- a/tests/misc/oracle/custom_machdep.res.oracle
+++ b/tests/misc/oracle/custom_machdep.res.oracle
@@ -1,4 +1,3 @@
-[kernel] Registering machdep 'mach' as 'custom'
 [kernel] Parsing custom_machdep.c (with preprocessing)
 /* Generated by Frama-C */
 #include "ctype.h"
@@ -19,12 +18,8 @@
 int main(void)
 {
   int __retres;
-  __retres = (int)2147483647;
+  __retres = 8388607 - 1;
   return __retres;
 }
 
 
-[kernel] Registering machdep 'mach' as 'custom'
-[kernel] Trying to register machdep 'mach2' as 'custom'
-[kernel] User Error: trying to register incompatible machdeps under name `custom'
-[kernel] Frama-C aborted: invalid user input.
diff --git a/tests/misc/oracle/print_machdep.res.oracle b/tests/misc/oracle/print_machdep.res.oracle
index 7c9a04850ea7f793b0235931ec0b95c651c2cead..b1566c66852eb15e98254fa0cfbaaf4a89ee1885 100644
--- a/tests/misc/oracle/print_machdep.res.oracle
+++ b/tests/misc/oracle/print_machdep.res.oracle
@@ -1,4 +1,4 @@
-Machine: gcc 4.0.3 AMD64
+Machine: gcc (GCC) 13.1.1 20230429
    sizeof       short =  2 (16 bits, aligned on 16 bits)
    sizeof         int =  4 (32 bits, aligned on 32 bits)
    sizeof        long =  8 (64 bits, aligned on 64 bits)
@@ -14,6 +14,4 @@ Machine: gcc 4.0.3 AMD64
    typeof   ptrdiff_t = long
    char is signed
    machine is little endian
-   strings are const chars
-   assembly names have no leading '_'
    compiler has builtin __va_list
diff --git a/tests/misc/oracle/stdint.0.res.oracle b/tests/misc/oracle/stdint.0.res.oracle
index 361bf0a731d25c48a5968997fe52adc755984705..09ab5559b6a1fc7f710aa034c89d37e44aa0c611 100644
--- a/tests/misc/oracle/stdint.0.res.oracle
+++ b/tests/misc/oracle/stdint.0.res.oracle
@@ -1,16 +1,16 @@
 [kernel] Parsing stdint.i (no preprocessing)
 [kernel] stdint.i:10: Warning: 
-  bad type 'int' (16 bits) for typedef 'int8_t';
+  bad type 'int' (16 bits) for typedef 'int8_t' using machdep machdep_x86_16;
   check for mismatch between -machdep flag and headers used
 [kernel] stdint.i:11: Warning: 
-  bad type 'unsigned char' (8 bits) for typedef 'uint_least64_t';
+  bad type 'unsigned char' (8 bits) for typedef 'uint_least64_t' using machdep machdep_x86_16;
   check for mismatch between -machdep flag and headers used
 [kernel] stdint.i:12: Warning: 
-  bad type 'short' (16 bits) for typedef 'int_fast32_t';
+  bad type 'short' (16 bits) for typedef 'int_fast32_t' using machdep machdep_x86_16;
   check for mismatch between -machdep flag and headers used
 [kernel] stdint.i:13: Warning: 
-  bad type 'char' (8 bits) for typedef 'intptr_t';
+  bad type 'char' (8 bits) for typedef 'intptr_t' using machdep machdep_x86_16;
   check for mismatch between -machdep flag and headers used
 [kernel] stdint.i:14: Warning: 
-  bad type 'unsigned short' (16 bits) for typedef 'uintmax_t';
+  bad type 'unsigned short' (16 bits) for typedef 'uintmax_t' using machdep machdep_x86_16;
   check for mismatch between -machdep flag and headers used
diff --git a/tests/misc/oracle/stdint.1.res.oracle b/tests/misc/oracle/stdint.1.res.oracle
index f293275aad7449242b56d10e4cc386e2970208e7..1bcb5d7a0942a3a28924e4678f5271d44dc3df45 100644
--- a/tests/misc/oracle/stdint.1.res.oracle
+++ b/tests/misc/oracle/stdint.1.res.oracle
@@ -1,16 +1,16 @@
 [kernel] Parsing stdint.i (no preprocessing)
 [kernel] stdint.i:10: Warning: 
-  bad type 'int' (32 bits) for typedef 'int8_t';
+  bad type 'int' (32 bits) for typedef 'int8_t' using machdep machdep_ppc_32;
   check for mismatch between -machdep flag and headers used
 [kernel] stdint.i:11: Warning: 
-  bad type 'unsigned char' (8 bits) for typedef 'uint_least64_t';
+  bad type 'unsigned char' (8 bits) for typedef 'uint_least64_t' using machdep machdep_ppc_32;
   check for mismatch between -machdep flag and headers used
 [kernel] stdint.i:12: Warning: 
-  bad type 'short' (16 bits) for typedef 'int_fast32_t';
+  bad type 'short' (16 bits) for typedef 'int_fast32_t' using machdep machdep_ppc_32;
   check for mismatch between -machdep flag and headers used
 [kernel] stdint.i:13: Warning: 
-  bad type 'char' (8 bits) for typedef 'intptr_t';
+  bad type 'char' (8 bits) for typedef 'intptr_t' using machdep machdep_ppc_32;
   check for mismatch between -machdep flag and headers used
 [kernel] stdint.i:14: Warning: 
-  bad type 'unsigned short' (16 bits) for typedef 'uintmax_t';
+  bad type 'unsigned short' (16 bits) for typedef 'uintmax_t' using machdep machdep_ppc_32;
   check for mismatch between -machdep flag and headers used
diff --git a/tests/misc/oracle/stdint.2.res.oracle b/tests/misc/oracle/stdint.2.res.oracle
index f293275aad7449242b56d10e4cc386e2970208e7..7079c2fcd815cc8fae3a25d4b682b71360475c24 100644
--- a/tests/misc/oracle/stdint.2.res.oracle
+++ b/tests/misc/oracle/stdint.2.res.oracle
@@ -1,16 +1,16 @@
 [kernel] Parsing stdint.i (no preprocessing)
 [kernel] stdint.i:10: Warning: 
-  bad type 'int' (32 bits) for typedef 'int8_t';
+  bad type 'int' (32 bits) for typedef 'int8_t' using machdep machdep_msvc_x86_64;
   check for mismatch between -machdep flag and headers used
 [kernel] stdint.i:11: Warning: 
-  bad type 'unsigned char' (8 bits) for typedef 'uint_least64_t';
+  bad type 'unsigned char' (8 bits) for typedef 'uint_least64_t' using machdep machdep_msvc_x86_64;
   check for mismatch between -machdep flag and headers used
 [kernel] stdint.i:12: Warning: 
-  bad type 'short' (16 bits) for typedef 'int_fast32_t';
+  bad type 'short' (16 bits) for typedef 'int_fast32_t' using machdep machdep_msvc_x86_64;
   check for mismatch between -machdep flag and headers used
 [kernel] stdint.i:13: Warning: 
-  bad type 'char' (8 bits) for typedef 'intptr_t';
+  bad type 'char' (8 bits) for typedef 'intptr_t' using machdep machdep_msvc_x86_64;
   check for mismatch between -machdep flag and headers used
 [kernel] stdint.i:14: Warning: 
-  bad type 'unsigned short' (16 bits) for typedef 'uintmax_t';
+  bad type 'unsigned short' (16 bits) for typedef 'uintmax_t' using machdep machdep_msvc_x86_64;
   check for mismatch between -machdep flag and headers used
diff --git a/tests/pretty_printing/test_config b/tests/pretty_printing/test_config
index 5feb4989bf0a2bfd00639668a9521d46037895a4..ada89b488ceb4a09d2ed04c6e273ab0c6c3e99ad 100644
--- a/tests/pretty_printing/test_config
+++ b/tests/pretty_printing/test_config
@@ -2,5 +2,4 @@ COMMENT: this directory is meant to test the parser and pretty-printer
 COMMENT: the default option checks that pretty-printed code can be merged
 COMMENT: with the original one
 PLUGIN:
-CMD: FRAMAC_PLUGIN=tests/.empty @frama-c@
 OPT: @PTEST_FILE@ -print -then -ocode ./ocode_@PTEST_NAME@.c -print -then ./ocode_@PTEST_NAME@.c @PTEST_FILE@ -ocode="" -print
diff --git a/tests/spec/array_conversion.c b/tests/spec/array_conversion.c
index 930e58c457654fb23a1400d44a7feb03e0957548..3313cb3ecb8d72c3445d3060cb51a19660a4e106 100644
--- a/tests/spec/array_conversion.c
+++ b/tests/spec/array_conversion.c
@@ -36,3 +36,7 @@ void ftest(void) {
 
 
 //@ lemma array_not_null: a != \null; 
+
+int const ca[1] = { 0 };
+
+//@ lemma const_array_init: \initialized(&ca[0]);
diff --git a/tests/spec/oracle/array_conversion.res.oracle b/tests/spec/oracle/array_conversion.res.oracle
index cdcd418791e268f2b97577be9be119b4cbb946c9..891a21b5b85b66a02e901e2df8adc8e946d06af3 100644
--- a/tests/spec/oracle/array_conversion.res.oracle
+++ b/tests/spec/oracle/array_conversion.res.oracle
@@ -45,6 +45,9 @@ void ftest(void)
 }
 
 /*@ lemma array_not_null{L}: (int *)a ≢ \null;
+ */
+int const ca[1] = {0};
+/*@ lemma const_array_init{L}: \initialized((int const *)ca);
 
 */
 
diff --git a/tests/spec/oracle/ghost_array.res.oracle b/tests/spec/oracle/ghost_array.res.oracle
index 1b05dae72afda76b43e3679db1a3fa5dfa8a1bba..1681b804dd43e4d472f4a5e213b77e3487475860 100644
--- a/tests/spec/oracle/ghost_array.res.oracle
+++ b/tests/spec/oracle/ghost_array.res.oracle
@@ -10,8 +10,8 @@ uint32 s[2];
 /*@
 predicate equal_t_s{L}(ℤ i) =
   \at(t[i] ≡
-      (unsigned long const)((uint16)(*((uint8 *)((uint32 *)s) + i) ≡
-                                     *(((uint8 *)((uint32 *)s) + i) + 1))),
+      (unsigned long)((uint16)(*((uint8 *)((uint32 *)s) + i) ≡
+                               *(((uint8 *)((uint32 *)s) + i) + 1))),
       L);
  */
 uint8 Array[10];
@@ -23,10 +23,9 @@ predicate mypredl{L}=
   ∀ ℤ MyNum;
     0 ≤ MyNum < FCG_Number ⇒
     FCG_Var2[MyNum] ≡
-    (unsigned long \ghost)((uint16)(*((uint8 *)(&Array[FCG_Var1[MyNum]] + 1))
-                                    * 256 +
-                                    *((uint8 *)((&Array[FCG_Var1[MyNum]] +
-                                                 (1 + 2))
-                                                + 1))));
+    (unsigned long)((uint16)(*((uint8 *)(&Array[FCG_Var1[MyNum]] + 1)) * 256
+                             +
+                             *((uint8 *)((&Array[FCG_Var1[MyNum]] + (1 + 2))
+                                         + 1))));
  */
 
diff --git a/tests/spec/oracle/ghost_array_pretty.c b/tests/spec/oracle/ghost_array_pretty.c
index 658b0f698a998b028f103de603f45cb5a27ca61f..b02d5fd80ff35ac08f02a0e58ac2066c8e6ca5cb 100644
--- a/tests/spec/oracle/ghost_array_pretty.c
+++ b/tests/spec/oracle/ghost_array_pretty.c
@@ -8,8 +8,8 @@ uint32 s[2];
 /*@
 predicate equal_t_s{L}(ℤ i) =
   \at(t[i] ≡
-      (unsigned long const)((uint16)(*((uint8 *)((uint32 *)s) + i) ≡
-                                     *(((uint8 *)((uint32 *)s) + i) + 1))),
+      (unsigned long)((uint16)(*((uint8 *)((uint32 *)s) + i) ≡
+                               *(((uint8 *)((uint32 *)s) + i) + 1))),
       L);
  */
 uint8 Array[10];
@@ -21,10 +21,9 @@ predicate mypredl{L}=
   ∀ ℤ MyNum;
     0 ≤ MyNum < FCG_Number ⇒
     FCG_Var2[MyNum] ≡
-    (unsigned long \ghost)((uint16)(*((uint8 *)(&Array[FCG_Var1[MyNum]] + 1))
-                                    * 256 +
-                                    *((uint8 *)((&Array[FCG_Var1[MyNum]] +
-                                                 (1 + 2))
-                                                + 1))));
+    (unsigned long)((uint16)(*((uint8 *)(&Array[FCG_Var1[MyNum]] + 1)) * 256
+                             +
+                             *((uint8 *)((&Array[FCG_Var1[MyNum]] + (1 + 2))
+                                         + 1))));
  */
 
diff --git a/tests/spec/oracle/kw.res.oracle b/tests/spec/oracle/kw.res.oracle
index 8b6bdc8c2cc9b20df7e9ad0f3a7725e26d9855f8..cdc7824e878babe57e329155cace996037d20b38 100644
--- a/tests/spec/oracle/kw.res.oracle
+++ b/tests/spec/oracle/kw.res.oracle
@@ -30,7 +30,7 @@ int main(void)
   struct custom writes;
   struct at include;
   struct loop assert;
-  /*@ slevel 4; */
+  /*@ slevel 4; */ ;
   behavior ++;
   /*@
   assert
diff --git a/tests/spec/oracle/polymorphic_inductive.res.oracle b/tests/spec/oracle/polymorphic_inductive.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..f003162d035a68df660507c0df1a4a579ca6e527
--- /dev/null
+++ b/tests/spec/oracle/polymorphic_inductive.res.oracle
@@ -0,0 +1,8 @@
+[kernel] Parsing polymorphic_inductive.i (no preprocessing)
+/* Generated by Frama-C */
+/*@
+inductive P<A>(A i, \list<A>  s) {
+  case one<A>: ∀ A a, \list<A>  s; \Cons(a, s) ≡ [| a |] ⇒ P(a, s);
+  }
+ */
+
diff --git a/tests/spec/polymorphic_inductive.i b/tests/spec/polymorphic_inductive.i
new file mode 100644
index 0000000000000000000000000000000000000000..c972f6c494a69c7129bc8a8e72fce8c64591f51f
--- /dev/null
+++ b/tests/spec/polymorphic_inductive.i
@@ -0,0 +1,5 @@
+/*@ inductive P<A>(A i, \list<A> s){
+    case one<A>: 
+      \forall A a, \list<A> s ; \Cons(a, s) == [| a |] ==> P(a, s);
+    }
+*/
diff --git a/tests/spec/property_test.ml b/tests/spec/property_test.ml
index 00407c161ac46f53abe7aa0ccd0f38fc3d5a203d..9088cf306802455e82893b4042ccd39921790e5c 100644
--- a/tests/spec/property_test.ml
+++ b/tests/spec/property_test.ml
@@ -10,9 +10,9 @@ class visit prj =
     method! vbehavior b =
       let kf = Option.get self#current_kf in
       if Kernel_function.get_name kf = "main" then begin
-        let x = Globals.Vars.find_from_astinfo "X" VGlobal in
+        let x = Globals.Vars.find_from_astinfo "X" Global in
         let x = Cil.cvar_to_lvar x in
-        let c = Globals.Vars.find_from_astinfo "c" (VFormal kf) in
+        let c = Globals.Vars.find_from_astinfo "c" (Formal kf) in
         let c = Cil.cvar_to_lvar c in
         b.b_assigns <-
           Writes
diff --git a/tests/syntax/assembly_gmp.c b/tests/syntax/assembly_gmp.c
index 0d39854c42ebfe3febd235f71c57c8f1622c99ba..fb707e0976786536b638ca7bb56e24bddab1e60b 100644
--- a/tests/syntax/assembly_gmp.c
+++ b/tests/syntax/assembly_gmp.c
@@ -86,7 +86,7 @@ File modified by CEA LIST for inclusion in Frama-C test suite
 #endif
 
 #ifndef add_mssaaaa
-#error "This test must run with machdep equals to x86_32, x86_64 or ppc_32"
+#error "This test must run with machdep equals to gcc_x86_32, gcc_x86_64, or ppc_32"
 #endif
 
 #define umul_ppmm(ph, pl, m0, m1) \
diff --git a/tests/syntax/char_is_unsigned.i b/tests/syntax/char_is_unsigned.i
index 02a2088fef3e3a4aa038f1bd41a176bd45e36cf1..e5a954b1ed03f0e50ec53ee0ba233ed5cd3070d7 100644
--- a/tests/syntax/char_is_unsigned.i
+++ b/tests/syntax/char_is_unsigned.i
@@ -1,7 +1,6 @@
 /* run.config
 PLUGIN: rtegen
- MODULE: machdep_char_unsigned
-   OPT: -print -machdep unsigned_char -then -constfold -rte
+   OPT: -print -machdep %{dep:@PTEST_DIR@/machdep_char_unsigned.yaml} -then -constfold -rte
 */
 char t[10];
 
diff --git a/tests/syntax/cpp-command.c b/tests/syntax/cpp-command.c
index af14a03a707cf3bfb577e1cbdbd80ce4e5c0eecb..5d0140181679d20deb6837e16bd854a804dc757e 100644
--- a/tests/syntax/cpp-command.c
+++ b/tests/syntax/cpp-command.c
@@ -1,5 +1,5 @@
 /* run.config*
-   FILTER: sed "s:/[^ ]*[/]cpp-command\.[^ ]*\.i:TMPDIR/FILE.i:g; s:$PWD/::g; s:$(realpath @FRAMAC_SHARE@)/:FRAMAC_SHARE/:g; s:@PTEST_MAKE_DIR@/result@PTEST_CONFIG@/::g; s: -m32::; s: -m64::"
+   FILTER: sed "s:/[^ ]*[/]cpp-command\.[^ ]*\.i:TMPDIR/FILE.i:g; s:[^ ]*[/]__fc_machdep.*\.dir:-ITMP_MACHDEP:g; s:$PWD/::g; s:$(realpath @FRAMAC_SHARE@)/:FRAMAC_SHARE/:g; s:@PTEST_MAKE_DIR@/result@PTEST_CONFIG@/::g; s: -m32::; s: -m64::"
    OPT: -machdep x86_32 -cpp-frama-c-compliant -cpp-command "echo [\$(basename '%1') \$(basename '%1') \$(basename '%i') \$(basename '%input')] ['%2' '%2' '%o' '%output'] ['%args']"
    OPT: -machdep x86_32 -cpp-frama-c-compliant -cpp-command "echo %%1 = \$(basename '%1') %%2 = '%2' %%args = '%args'"
    OPT: -machdep x86_32 -cpp-frama-c-compliant -cpp-command "printf \"%s\n\" \"using \\% has no effect : \$(basename \"\%input\")\""
diff --git a/tests/syntax/get_astinfo_bts1136.ml b/tests/syntax/get_astinfo_bts1136.ml
index 98c338bf7c935b57c284e2392d2380a4460982b8..e842f7e046d687f023eca1e6c8563c03d6d33ccf 100644
--- a/tests/syntax/get_astinfo_bts1136.ml
+++ b/tests/syntax/get_astinfo_bts1136.ml
@@ -2,7 +2,7 @@
 let get_formal_variables name =
   let add_kf_vars kf vars =
     try
-      let v = Globals.Vars.find_from_astinfo name (Cil_types.VFormal kf) in
+      let v = Globals.Vars.find_from_astinfo name (Cil_types.Formal kf) in
       Format.printf "found variable vid:%d formal in %a@."
         v.Cil_types.vid Cil_datatype.Kf.pretty kf;
       v::vars
@@ -14,7 +14,8 @@ let get_formal_variables name =
 let get_local_variables name =
   let add_kf_vars kf vars =
     try
-      let v = Globals.Vars.find_from_astinfo name (Cil_types.VLocal kf) in
+      let v = Globals.Vars.find_from_astinfo name (Cil_types.Whole_function kf)
+      in
       Format.printf "found variable vid:%d formal in %a@."
         v.Cil_types.vid Cil_datatype.Kf.pretty kf;
       v::vars
@@ -30,16 +31,9 @@ let main () =
   let vars = get_formal_variables "x" in
   let vars' = get_local_variables "y" in
   let do_v v =
-    let pp_kind fmt kind = match kind with
-      | Cil_types.VGlobal -> Format.fprintf fmt "global"
-      | Cil_types.VFormal kf ->
-        Format.fprintf fmt "formal in %a" Cil_datatype.Kf.pretty kf
-      | Cil_types.VLocal kf ->
-        Format.fprintf fmt "local in %a" Cil_datatype.Kf.pretty kf
-    in
     let _, kind = Globals.Vars.get_astinfo v in
     Format.printf "[do_v] vid:%d %a@."  v.Cil_types.vid
-      (* Cil_datatype.Localisation.pretty *) pp_kind kind
+      Cil_datatype.Syntactic_scope.pretty kind
   in List.iter do_v vars; List.iter do_v vars'
 
 let () = Db.Main.extend main
diff --git a/tests/syntax/machdep_char_unsigned.ml b/tests/syntax/machdep_char_unsigned.ml
index 2e0a28c35f4145122f84813999c726cd0315ffb3..034b0ca6fe72d47b36ca1056bd8b8297d424a59e 100644
--- a/tests/syntax/machdep_char_unsigned.ml
+++ b/tests/syntax/machdep_char_unsigned.ml
@@ -1,4 +1,3 @@
-
 open Cil_types
 
 let md = {
@@ -27,13 +26,47 @@ let md = {
   alignof_fun = 0;
   alignof_aligned= 0;
   char_is_unsigned = true;
-  const_string_literals = true;
   little_endian = true;
-  underscore_name = true ;
   size_t = "unsigned int";
+  ssize_t = "int";
   wchar_t = "int";
+  intptr_t = "int";
+  uintptr_t = "unsigned int";
+  int_fast8_t = "signed char";
+  int_fast16_t = "long";
+  int_fast32_t = "long";
+  int_fast64_t = "long";
+  uint_fast8_t = "unsigned char";
+  uint_fast16_t = "unsigned long";
+  uint_fast32_t = "unsigned long";
+  uint_fast64_t = "usigned long";
   ptrdiff_t = "int";
+  wint_t = "long";
+  sig_atomic_t = "int";
+  time_t = "long";
   has__builtin_va_list = true;
+  weof = "(-1L)";
+  wordsize = "16";
+  posix_version = "";
+  bufsiz = "8192";
+  eof = "(-1)";
+  fopen_max = "16";
+  host_name_max = "255";
+  tty_name_max = "255";
+  path_max = "255";
+  filename_max = "2048";
+  l_tmpnam = "2048";
+  tmp_max = "0xFFFFFFFF";
+  rand_max = "0xFFFFFFFE";
+  mb_cur_max = "16";
+  nsig = "64";
+  errno = [
+    "edom", "33";
+    "eilseq", "84";
+    "erange", "34";
+  ];
+  machdep_name = "machdep_char_unsigned";
+  custom_defs = "";
 }
 
 let () =
diff --git a/tests/syntax/machdep_char_unsigned.yaml b/tests/syntax/machdep_char_unsigned.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..cb4fbd6b6c6a360e076860b4e71b5794c463e17b
--- /dev/null
+++ b/tests/syntax/machdep_char_unsigned.yaml
@@ -0,0 +1,183 @@
+alignof_aligned: 0
+alignof_short: 2
+compiler: gcc
+version: 'N/A'
+cpp_arch_flags:
+- -m32
+sizeof_short: 2
+sizeof_int: 2
+sizeof_long: 4
+sizeof_longlong: 8
+sizeof_ptr: 4
+sizeof_float: 4
+sizeof_double: 8
+sizeof_longdouble: 8
+sizeof_void: -1
+sizeof_fun: 0
+alignof_int: 2
+alignof_long: 2
+alignof_longlong: 2
+alignof_ptr: 2
+alignof_float: 2
+alignof_double: 2
+alignof_longdouble: 2
+alignof_str: 0
+alignof_fun: 0
+char_is_unsigned: true
+little_endian: true
+size_t: 'unsigned int'
+ssize_t: 'int'
+wchar_t: 'int'
+intptr_t: 'int'
+uintptr_t: 'unsigned int'
+int_fast8_t: 'signed char'
+int_fast16_t: 'long'
+int_fast32_t: 'long'
+int_fast64_t: 'long'
+uint_fast8_t: 'unsigned char'
+uint_fast16_t: 'unsigned long'
+uint_fast32_t: 'unsigned long'
+uint_fast64_t: 'unsigned long'
+ptrdiff_t: 'int'
+wint_t: 'long'
+sig_atomic_t: 'int'
+time_t: 'long'
+has__builtin_va_list: true
+weof: '(-1L)'
+wordsize: '16'
+posix_version: ''
+bufsiz: '8192'
+eof: '(-1)'
+fopen_max: '16'
+host_name_max: '255'
+tty_name_max: '255'
+path_max: '255'
+filename_max: '2048'
+l_tmpnam: '2048'
+tmp_max: '0xFFFFFFFF'
+rand_max: '0xFFFFFFFE'
+mb_cur_max: '16'
+nsig: '64'
+errno:
+    e2big: '7'
+    eacces: '13'
+    eaddrinuse: '98'
+    eaddrnotavail: '99'
+    eafnosupport: '97'
+    eagain: '11'
+    ealready: '114'
+    ebade: '52'
+    ebadf: '9'
+    ebadfd: '77'
+    ebadmsg: '74'
+    ebadr: '53'
+    ebadrqc: '56'
+    ebadslt: '57'
+    ebusy: '16'
+    ecanceled: '125'
+    echild: '10'
+    echrng: '44'
+    ecomm: '70'
+    econnaborted: '103'
+    econnrefused: '111'
+    econnreset: '104'
+    edeadlk: '35'
+    edeadlock: '35'
+    edestaddrreq: '89'
+    edom: '33'
+    edquot: '122'
+    eexist: '17'
+    efault: '14'
+    efbig: '27'
+    ehostdown: '112'
+    ehostunreach: '113'
+    eidrm: '43'
+    eilseq: '84'
+    einprogress: '115'
+    eintr: '4'
+    einval: '22'
+    eio: '5'
+    eisconn: '106'
+    eisdir: '21'
+    eisnam: '120'
+    ekeyexpired: '127'
+    ekeyrejected: '129'
+    ekeyrevoked: '128'
+    el2hlt: '51'
+    el2nsync: '45'
+    el3hlt: '46'
+    el3rst: '47'
+    elibacc: '79'
+    elibbad: '80'
+    elibexec: '83'
+    elibmax: '82'
+    elibscn: '81'
+    eloop: '40'
+    emediumtype: '124'
+    emfile: '24'
+    emlink: '31'
+    emsgsize: '90'
+    emultihop: '72'
+    enametoolong: '36'
+    enetdown: '100'
+    enetreset: '102'
+    enetunreach: '101'
+    enfile: '23'
+    enobufs: '105'
+    enodata: '61'
+    enodev: '19'
+    enoent: '2'
+    enoexec: '8'
+    enokey: '126'
+    enolck: '37'
+    enolink: '67'
+    enomedium: '123'
+    enomem: '12'
+    enomsg: '42'
+    enonet: '64'
+    enopkg: '65'
+    enoprotoopt: '92'
+    enospc: '28'
+    enosr: '63'
+    enostr: '60'
+    enosys: '38'
+    enotblk: '15'
+    enotconn: '107'
+    enotdir: '20'
+    enotempty: '39'
+    enotsock: '88'
+    enotsup: '95'
+    enotty: '25'
+    enotuniq: '76'
+    enxio: '6'
+    eopnotsupp: '95'
+    eoverflow: '75'
+    eperm: '1'
+    epfnosupport: '96'
+    epipe: '32'
+    eproto: '71'
+    eprotonosupport: '93'
+    eprototype: '91'
+    erange: '34'
+    eremchg: '78'
+    eremote: '66'
+    eremoteio: '121'
+    erestart: '85'
+    erofs: '30'
+    eshutdown: '108'
+    esocktnosupport: '94'
+    espipe: '29'
+    esrch: '3'
+    estale: '116'
+    estrpipe: '86'
+    etime: '62'
+    etimedout: '110'
+    etxtbsy: '26'
+    euclean: '117'
+    eunatch: '49'
+    eusers: '87'
+    ewouldblock: '11'
+    exdev: '18'
+    exfull: '54'
+machdep_name: 'machdep_char_unsigned'
+custom_defs: ''
diff --git a/tests/syntax/oracle/cpp-command.0.res.oracle b/tests/syntax/oracle/cpp-command.0.res.oracle
index e10baa0dfad5c10cedc7a23bc926b110277f5129..914862fa5a3192563071d1233952c09acfbf8ef5 100644
--- a/tests/syntax/oracle/cpp-command.0.res.oracle
+++ b/tests/syntax/oracle/cpp-command.0.res.oracle
@@ -1,2 +1,2 @@
 [kernel] Parsing cpp-command.c (with preprocessing)
-[cpp-command.c cpp-command.c cpp-command.c cpp-command.c] [TMPDIR/FILE.i TMPDIR/FILE.i TMPDIR/FILE.i TMPDIR/FILE.i] [-IFRAMAC_SHARE/libc -D__FRAMAC__ -D__FC_MACHDEP_X86_32 -dD -nostdinc]
+[cpp-command.c cpp-command.c cpp-command.c cpp-command.c] [TMPDIR/FILE.i TMPDIR/FILE.i TMPDIR/FILE.i TMPDIR/FILE.i] -ITMP_MACHDEP -IFRAMAC_SHARE/libc -D__FRAMAC__ -dD -nostdinc]
diff --git a/tests/syntax/oracle/cpp-command.1.res.oracle b/tests/syntax/oracle/cpp-command.1.res.oracle
index f0b357a6deb2d9063b3f13d79524c9699c7237c7..6d8ee3a2017974d5b635775c02a3cf7abc5928fd 100644
--- a/tests/syntax/oracle/cpp-command.1.res.oracle
+++ b/tests/syntax/oracle/cpp-command.1.res.oracle
@@ -1,2 +1,2 @@
 [kernel] Parsing cpp-command.c (with preprocessing)
-%1 = cpp-command.c %2 = TMPDIR/FILE.i %args = -IFRAMAC_SHARE/libc -D__FRAMAC__ -D__FC_MACHDEP_X86_32 -dD -nostdinc
+%1 = cpp-command.c %2 = TMPDIR/FILE.i %args = -ITMP_MACHDEP -IFRAMAC_SHARE/libc -D__FRAMAC__ -dD -nostdinc
diff --git a/tests/syntax/oracle/cpp-command.4.res.oracle b/tests/syntax/oracle/cpp-command.4.res.oracle
index c53f47b8877f466385ba44e02528ee98be75f667..e42375af42082ed6fd520737d8a4bde16a1b9289 100644
--- a/tests/syntax/oracle/cpp-command.4.res.oracle
+++ b/tests/syntax/oracle/cpp-command.4.res.oracle
@@ -1,2 +1,2 @@
 [kernel] Preprocessing command:
-  gcc -E -C -I. -IFRAMAC_SHARE/libc -D__FRAMAC__ -D__FC_MACHDEP_X86_32 -dD -nostdinc 'cpp-command.c' -o 'TMPDIR/FILE.i'
+  gcc -E -C -I. -ITMP_MACHDEP -IFRAMAC_SHARE/libc -D__FRAMAC__ -dD -nostdinc 'cpp-command.c' -o 'TMPDIR/FILE.i'
diff --git a/tests/syntax/oracle/cpp-command.6.res.oracle b/tests/syntax/oracle/cpp-command.6.res.oracle
index b27c0fedfd6cd125f87b61226d70d164b66d5dbe..ef44555760ec5721b7f94c555e0d657fec0858f6 100644
--- a/tests/syntax/oracle/cpp-command.6.res.oracle
+++ b/tests/syntax/oracle/cpp-command.6.res.oracle
@@ -1,7 +1,7 @@
 [kernel] Warning: your preprocessor is not known to handle option `-nostdinc'. If pre-processing fails because of it, please add -no-cpp-frama-c-compliant option to Frama-C's command-line. If you do not want to see this warning again, explicitly use option -cpp-frama-c-compliant.
 [kernel] Warning: your preprocessor is not known to handle option `-dD'. If pre-processing fails because of it, please add -no-cpp-frama-c-compliant option to Frama-C's command-line. If you do not want to see this warning again, explicitly use option -cpp-frama-c-compliant.
 [kernel] Parsing cpp-command.c (with preprocessing)
-extra_args: -IFRAMAC_SHARE/libc -D__FRAMAC__ -D__FC_MACHDEP_X86_64 -dD -nostdinc file_extra global_extra
+extra_args: -ITMP_MACHDEP -IFRAMAC_SHARE/libc -D__FRAMAC__ -dD -nostdinc file_extra global_extra
 [kernel] Warning: trying to preprocess annotation with an unknown preprocessor.
 /* Generated by Frama-C */
 
diff --git a/tests/syntax/oracle/get_astinfo_bts1136.res.oracle b/tests/syntax/oracle/get_astinfo_bts1136.res.oracle
index 4201820cc17bf86f68100ee87549a14636977e5d..9c4b065ef072af884ea981f90301358d6285755b 100644
--- a/tests/syntax/oracle/get_astinfo_bts1136.res.oracle
+++ b/tests/syntax/oracle/get_astinfo_bts1136.res.oracle
@@ -5,9 +5,9 @@ found variable vid:28 formal in h
 found variable vid:30 formal in i
 found variable vid:32 formal in j
 found variable vid:34 formal in k
-[do_v] vid:28 formal in h
-[do_v] vid:25 formal in g
-[do_v] vid:22 formal in f
-[do_v] vid:34 local in k
-[do_v] vid:32 local in j
-[do_v] vid:30 local in i
+[do_v] vid:28 Parameter of h
+[do_v] vid:25 Parameter of g
+[do_v] vid:22 Parameter of f
+[do_v] vid:34 Local variable of k
+[do_v] vid:32 Local variable of j
+[do_v] vid:30 Local variable of i
diff --git a/tests/value/ilevel.c b/tests/value/ilevel.c
new file mode 100644
index 0000000000000000000000000000000000000000..cd68ed54ea80a0f2202a7373c2563e064534bfa7
--- /dev/null
+++ b/tests/value/ilevel.c
@@ -0,0 +1,48 @@
+/* run.config*
+   PLUGIN: @EVA_MAIN_PLUGINS@ inout,slicing
+   OPT: -eva @EVA_CONFIG@ -slice-return main -then-on "Slicing export" -eva -eva-ilevel 16 -eva-show-progress -then-on "default" -eva-ilevel 17 -then -eva-ilevel 48
+   STDOPT: +"-eva-ilevel 400 -main large_ilevel"
+*/
+
+// Test in particular that ilevel is by-project, even though it is an ocaml ref
+
+#include "__fc_builtin.h"
+
+volatile int nondet;
+int i, j, k, l;
+
+int main () {
+  do { i = nondet; }
+  while (! (0 <= i && i < 8));
+
+  do { j = nondet; }
+  while (! (0 <= j && j < 17));
+
+  k = j;
+  if (k == 16) k = 15;
+
+  l = nondet;
+  if (nondet) {
+    //@ assert 0 <= l <= 4;
+  } else {
+    //@ assert 6 <= l <= 9;
+  }
+  Frama_C_show_each(l); // Possible problem with cache on offsetmap join
+
+  return i+j+k+l;
+}
+
+/* Tests printing large integer sets. */
+void large_ilevel (void) {
+  int i = Frama_C_interval(0, 10);
+  int j = nondet ? i : i - 25;
+  int k = Frama_C_interval(100, 200);
+  if (k == 128) return;
+
+  int a[11] = {53, 17, 64, 99, 25, 12, 72, 81, 404, 303, -101};
+
+  int s2 = nondet ? 40 : (nondet ? 41 : 42);
+  int s1 = a[i];
+
+  int x = nondet ? (nondet ? j : k) : (nondet ? s1 : s2);
+}
diff --git a/tests/value/ilevel.i b/tests/value/ilevel.i
deleted file mode 100644
index 30aaf6a78b8fe2795a46249604b5e0e6f7028aa7..0000000000000000000000000000000000000000
--- a/tests/value/ilevel.i
+++ /dev/null
@@ -1,27 +0,0 @@
-/* run.config*
- PLUGIN: @EVA_MAIN_PLUGINS@ inout,slicing
-   OPT: -eva @EVA_CONFIG@ -slice-return main -then-on "Slicing export" -eva -eva-ilevel 16 -eva-show-progress -then-on "default" -eva-ilevel 17 -then -eva-ilevel 48
-*/
-// Test in particular that ilevel is by-project, even though it is an ocaml ref
-volatile int v;
-int i, j, k, l;
-int main () {
-  do { i = v; }
-  while (! (0 <= i && i < 8));
-
-  do { j = v; }
-  while (! (0 <= j && j < 17));
-
-  k = j;
-  if (k == 16) k = 15;
-
-  l = v;
-  if (v) {
-    //@ assert 0 <= l <= 4;
-  } else {
-    //@ assert 6 <= l <= 9;
-  }
-  Frama_C_show_each(l); // Possible problem with cache on offsetmap join
-
-  return i+j+k+l;
-}
diff --git a/tests/value/octagons-pointers-intermediate.c b/tests/value/octagons-pointers-intermediate.c
new file mode 100644
index 0000000000000000000000000000000000000000..624055ae96f6783dc47202f8fc48c29561fd674c
--- /dev/null
+++ b/tests/value/octagons-pointers-intermediate.c
@@ -0,0 +1,49 @@
+/* run.config*
+   STDOPT: +" -eva-domains equality,octagon -eva-octagon-through-calls -eva-msg-key=d-octagon,-d-cvalue -eva-oracle-depth 10"
+*/
+
+#include <stdint.h>
+
+typedef struct cmd {
+  uint16_t cmdLen;
+  uint8_t cmdCode;
+} cmd_t;
+
+unsigned int const size = 436;
+unsigned char buffer[436];
+
+volatile char nondet;
+
+void init () {
+  for (int i = 0; i < size; i++) {
+    buffer[i] = nondet;
+  }
+}
+
+void cmdRead (unsigned char const *cmd, uint16_t cmdLen) {
+  uint16_t *len = (uint16_t *) cmd;
+  uint8_t *code = (uint8_t *) (len + 1);
+  uint32_t *elt1 = (uint32_t *) (code + 1);
+  uint16_t *elt2 = (uint16_t *) (elt1 + 1);
+  uint16_t *elt3 = (uint16_t *) (elt2 + 1);
+  if (cmdLen < sizeof(*code) + sizeof(*elt1) + sizeof(*elt2) + sizeof(*elt3))
+    return;
+  uint8_t c = *code;
+  uint32_t e1 = *elt1;
+  uint16_t e2 = *elt2;
+  uint16_t e3 = *elt3;
+}
+
+void main () {
+  init ();
+  unsigned int index = 3;
+  cmd_t *cmd = (cmd_t *) &buffer[index];
+  /*@ loop unroll 1; */
+  while ( index + sizeof(cmd->cmdLen) + sizeof(cmd->cmdCode) <= size &&
+          cmd->cmdLen != 0 &&
+          size - index - sizeof(cmd->cmdLen) >= cmd->cmdLen) {
+    cmdRead(&buffer[index], cmd->cmdLen);
+    index += cmd->cmdLen + sizeof(cmd->cmdLen);
+    cmd = (cmd_t *) &buffer[index];
+  }
+}
diff --git a/tests/value/octagons-pointers-simple.c b/tests/value/octagons-pointers-simple.c
new file mode 100644
index 0000000000000000000000000000000000000000..13fb7e5e01373438b6e079fdef6a76e62226cb7c
--- /dev/null
+++ b/tests/value/octagons-pointers-simple.c
@@ -0,0 +1,51 @@
+/* run.config*
+   STDOPT: +"-deterministic -eva-domains equality,octagon -eva-octagon-through-calls -eva-msg-key=d-octagon,-d-cvalue -eva-oracle-depth 10"
+*/
+
+#include <stdint.h>
+
+typedef struct cmd {
+  uint16_t cmdLen;
+  uint8_t cmdCode;
+} cmd_t;
+
+unsigned int const size = 436;
+unsigned char buffer[436];
+
+volatile char nondet;
+
+void init () {
+  for (int i = 0; i < size; i++) {
+    buffer[i] = nondet;
+  }
+}
+
+void cmdRead (unsigned char const *cmd, unsigned int cmdLen) {
+  uint16_t *len = (uint16_t *) cmd;
+  uint8_t *code = (uint8_t *) (len + 1);
+  uint32_t *elt1 = (uint32_t *) (code + 1);
+  uint16_t *elt2 = (uint16_t *) (elt1 + 1);
+  uint16_t *elt3 = (uint16_t *) (elt2 + 1);
+  if (cmdLen < sizeof(*code) + sizeof(*elt1) + sizeof(*elt2) + sizeof(*elt3))
+    return;
+  uint8_t c = *code;
+  uint32_t e1 = *elt1;
+  uint16_t e2 = *elt2;
+  uint16_t e3 = *elt3;
+}
+
+void main () {
+  init ();
+  unsigned int index = 3;
+  unsigned int cmdLen;
+  cmd_t *cmd = (cmd_t *) &buffer[index];
+  /*@ loop unroll 1; */
+  while ( index + sizeof(cmd->cmdLen) + sizeof(cmd->cmdCode) <= size &&
+          (cmdLen = cmd->cmdLen, cmdLen != 0) &&
+          size - index - sizeof(cmd->cmdLen) >= cmdLen) {
+    Frama_C_dump_each();
+    cmdRead(&buffer[index], cmdLen);
+    index += cmdLen + sizeof(cmd->cmdLen);
+    cmd = (cmd_t *) &buffer[index];
+  }
+}
diff --git a/tests/value/octagons-pointers.c b/tests/value/octagons-pointers.c
new file mode 100644
index 0000000000000000000000000000000000000000..6eb96783523b29ec75cdb807c294c1069f831bfe
--- /dev/null
+++ b/tests/value/octagons-pointers.c
@@ -0,0 +1,80 @@
+/* run.config*
+   STDOPT: +"-deterministic -eva-domains equality,octagon -eva-octagon-through-calls -eva-msg-key=d-octagon,-d-cvalue -eva-oracle-depth 10"
+*/
+
+#include <stdint.h>
+
+typedef struct cmd {
+  uint16_t cmdLen;
+  uint8_t cmdCode;
+} cmd_t;
+
+unsigned int const size = 436;
+unsigned char buffer[436];
+
+volatile char nondet;
+
+void init () {
+  for (int i = 0; i < size; i++) {
+    buffer[i] = nondet;
+  }
+}
+
+void cmdRead (unsigned char const *cmd) {
+  uint16_t *len = (uint16_t *) cmd;
+  uint8_t *code = (uint8_t *) (len + 1);
+  uint32_t *elt1 = (uint32_t *) (code + 1); // elt1 = cmd + 3
+  uint16_t *elt2 = (uint16_t *) (elt1 + 1);
+  uint16_t *elt3 = (uint16_t *) (elt2 + 1);
+  if (*len < sizeof(*code) + sizeof(*elt1) + sizeof(*elt2) + sizeof(*elt3)) // cmd->cmdLen >= m
+    return;
+  Frama_C_dump_each();
+  uint8_t c = *code;
+  uint32_t e1 = *elt1;
+  uint16_t e2 = *elt2;
+  uint16_t e3 = *elt3;
+}
+
+void main () {
+  init ();
+  unsigned int index = 3;
+  cmd_t *cmd = (cmd_t *) &buffer[index];
+  /*@ loop unroll 1; */
+  while ( index + sizeof(cmd->cmdLen) + sizeof(cmd->cmdCode) <= size &&
+          cmd->cmdLen != 0 &&
+          size - index - sizeof(cmd->cmdLen) >= cmd->cmdLen) { // index <= n - cmd->cmdLen
+    Frama_C_dump_each();
+    cmdRead(&buffer[index]); // cmd = buffer + index
+    index += cmd->cmdLen + sizeof(cmd->cmdLen);
+    cmd = (cmd_t *) &buffer[index];
+  }
+}
+
+#include "__fc_builtin.h"
+
+void main2(void) {
+    int t[10];
+    int i = Frama_C_interval(0,9);
+    int* p = t + i;
+
+    while (p < &t[10]) {
+        Frama_C_dump_each1();
+        *p = 0;
+        Frama_C_dump_each2();
+        p++;
+        Frama_C_dump_each3();
+    }
+}
+
+void main3 () {
+  int index = 3;
+  int x = Frama_C_interval(0,100);
+  /*@ loop unroll 1; */
+  while (500 - index >= x) {
+    Frama_C_dump_each();
+    index += x + 4;
+    Frama_C_dump_each();
+    x = Frama_C_interval(0,100);
+    Frama_C_dump_each();
+  }
+}
diff --git a/tests/value/octagons.c b/tests/value/octagons.c
index 7d51ba33e9b0242b54e636178ea71db939b7a960..a9428a90e4e6f4b052e9cde3e4514584a8e6b2f4 100644
--- a/tests/value/octagons.c
+++ b/tests/value/octagons.c
@@ -1,5 +1,5 @@
 /* run.config*
-   STDOPT: +" -eva-domains octagon -eva-octagon-through-calls -eva-msg-key=d-octagon,-d-cvalue"
+   STDOPT: +"-deterministic -eva-domains octagon -eva-octagon-through-calls -eva-msg-key=d-octagon,-d-cvalue"
 */
 
 #include <__fc_builtin.h>
diff --git a/tests/value/oracle/behaviors2.res.oracle b/tests/value/oracle/behaviors2.res.oracle
index bafc5e57b43b62c8f379e4bd48f6f9d8b15b71ad..6393f4f90fe5d5e3d5157491e386633a660d7a79 100644
--- a/tests/value/oracle/behaviors2.res.oracle
+++ b/tests/value/oracle/behaviors2.res.oracle
@@ -218,14 +218,14 @@
   remainder ∈ [--..--]
   sign ∈ {-1; 0; 1}
   errmsg[0..19] ∈ [--..--] or UNINITIALIZED
-  r1 ∈ {0}
-  r2 ∈ {0}
-  r3 ∈ {0}
-  r4 ∈ {1}
-  r5 ∈ {2}
-  r6 ∈ {2}
-  r7 ∈ {2}
-  r8 ∈ {0; 1}
+  r1 ∈ {OK}
+  r2 ∈ {OK}
+  r3 ∈ {OK}
+  r4 ∈ {DIVBYZERO}
+  r5 ∈ {INVALID_PARAMETER}
+  r6 ∈ {INVALID_PARAMETER}
+  r7 ∈ {INVALID_PARAMETER}
+  r8 ∈ {OK; DIVBYZERO}
 [eva:final-states] Values at end of function test2:
   a ∈ {1}
   b ∈ {2}
diff --git a/tests/value/oracle/enum.res.oracle b/tests/value/oracle/enum.res.oracle
index c65343692b545464ab010a6e10926ed10f81c934..52445e88edf1db1f197815d29402acc5da52dbd5 100644
--- a/tests/value/oracle/enum.res.oracle
+++ b/tests/value/oracle/enum.res.oracle
@@ -21,8 +21,8 @@
    [2] ∈ {36}
   i[0..1] ∈ {0; 1}
    [2] ∈ {0}
-  j ∈ {2}
-  k ∈ {0}
+  j ∈ {LAST}
+  k ∈ {ZERO}
 [from] Computing for function f
 [from] Done for function f
 [from] ====== DEPENDENCIES COMPUTED ======
diff --git a/tests/value/oracle/enum2.res.oracle b/tests/value/oracle/enum2.res.oracle
index 1344f4349e7a1a9fc0a7699fb318922b18819ba9..b82181fdbb735edd8146ee8644f4f4e22fbdd95b 100644
--- a/tests/value/oracle/enum2.res.oracle
+++ b/tests/value/oracle/enum2.res.oracle
@@ -26,7 +26,7 @@
 [eva:final-states] Values at end of function enum1_sgn1_inf_sgn0:
   res ∈ {0}
 [eva:final-states] Values at end of function f:
-  y ∈ {2557891634}
+  y ∈ {E1_SGN1}
 [eva:final-states] Values at end of function enum1_sgn1_positif:
   res ∈ {1}
 [eva:final-states] Values at end of function main:
diff --git a/tests/value/oracle/gauges.res.oracle b/tests/value/oracle/gauges.res.oracle
index a66e8eeac602b5dbc6fd77605d99074e76b1b212..683d5cd6e3ab18da6c43e6ae0f5f6d51be468471 100644
--- a/tests/value/oracle/gauges.res.oracle
+++ b/tests/value/oracle/gauges.res.oracle
@@ -343,7 +343,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -403,7 +403,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -462,7 +462,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -521,7 +521,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -586,7 +586,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -647,7 +647,7 @@
   # cvalue:
   __fc_heap_status ∈ [--..--]
   __fc_random_counter ∈ [--..--]
-  __fc_rand_max ∈ {32767}
+  __fc_rand_max ∈ {2147483647}
   __fc_random48_init ∈ {0}
   __fc_random48_counter[0..2] ∈ [--..--]
   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
diff --git a/tests/value/oracle/if2.res.oracle b/tests/value/oracle/if2.res.oracle
index aa0d25b661f5aa644ad27e7dc40e19029d216dc1..ed155b5d81b1877ce127863e2b0487d3fc661b9d 100644
--- a/tests/value/oracle/if2.res.oracle
+++ b/tests/value/oracle/if2.res.oracle
@@ -3,12 +3,12 @@
 [eva] Computing initial state
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
-  G2 ∈ {0}
+  G2 ∈ {E1}
   G3 ∈ {75}
   G4 ∈ {0}
   R ∈ {0}
   v ∈ [--..--]
-  G1 ∈ {0}
+  G1 ∈ {E1}
 [eva] Recording results for main
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
diff --git a/tests/value/oracle/ilevel.res.oracle b/tests/value/oracle/ilevel.0.res.oracle
similarity index 68%
rename from tests/value/oracle/ilevel.res.oracle
rename to tests/value/oracle/ilevel.0.res.oracle
index 042c98daaa39125f33b39a30cbfe8798a9b6d8b4..897c9e808ca3ad9d067d85a82e9051411385263d 100644
--- a/tests/value/oracle/ilevel.res.oracle
+++ b/tests/value/oracle/ilevel.0.res.oracle
@@ -1,18 +1,18 @@
-[kernel] Parsing ilevel.i (no preprocessing)
+[kernel] Parsing ilevel.c (with preprocessing)
 [eva] Analyzing a complete application starting at main
 [eva] Computing initial state
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
-  v ∈ [--..--]
+  nondet ∈ [--..--]
   i ∈ {0}
   j ∈ {0}
   k ∈ {0}
   l ∈ {0}
-[eva] ilevel.i:9: starting to merge loop iterations
-[eva] ilevel.i:12: starting to merge loop iterations
-[eva:alarm] ilevel.i:20: Warning: assertion got status unknown.
-[eva:alarm] ilevel.i:22: Warning: assertion got status unknown.
-[eva] ilevel.i:24: Frama_C_show_each: [0..9]
+[eva] ilevel.c:15: starting to merge loop iterations
+[eva] ilevel.c:18: starting to merge loop iterations
+[eva:alarm] ilevel.c:26: Warning: assertion got status unknown.
+[eva:alarm] ilevel.c:28: Warning: assertion got status unknown.
+[eva] ilevel.c:30: Frama_C_show_each: [0..9]
 [eva] Recording results for main
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
@@ -43,14 +43,14 @@
 [eva] Computing initial state
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
-  v ∈ [--..--]
+  nondet ∈ [--..--]
   i ∈ {0}
   j ∈ {0}
   k ∈ {0}
   l ∈ {0}
-[eva] ilevel.i:9: starting to merge loop iterations
-[eva] ilevel.i:12: starting to merge loop iterations
-[eva:alarm] ilevel.i:26: Warning: 
+[eva] ilevel.c:15: starting to merge loop iterations
+[eva] ilevel.c:18: starting to merge loop iterations
+[eva:alarm] ilevel.c:32: Warning: 
   signed overflow. assert (int)((int)(i + j) + k) + l ≤ 2147483647;
 [eva] Recording results for main
 [eva] done for function main
@@ -58,47 +58,44 @@
 [eva:final-states] Values at end of function main:
   i ∈ {0; 1; 2; 3; 4; 5; 6; 7}
   j ∈ [0..16]
-  k ∈ {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15}
+  k ∈ [0..15]
   l ∈ [--..--]
   __retres ∈ [--..--]
 [eva] Analyzing a complete application starting at main
 [eva] Computing initial state
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
-  v ∈ [--..--]
+  nondet ∈ [--..--]
   i ∈ {0}
   j ∈ {0}
   k ∈ {0}
   l ∈ {0}
-[eva] ilevel.i:24: Frama_C_show_each: {0; 1; 2; 3; 4; 6; 7; 8; 9}
+[eva] ilevel.c:30: Frama_C_show_each: {0; 1; 2; 3; 4; 6; 7; 8; 9}
 [eva] Recording results for main
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
 [eva:final-states] Values at end of function main:
   i ∈ {0; 1; 2; 3; 4; 5; 6; 7}
-  j ∈ {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16}
-  k ∈ {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15}
+  j ∈ [0..16]
+  k ∈ [0..15]
   l ∈ {0; 1; 2; 3; 4; 6; 7; 8; 9}
   __retres ∈ [0..47]
 [eva] Analyzing a complete application starting at main
 [eva] Computing initial state
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
-  v ∈ [--..--]
+  nondet ∈ [--..--]
   i ∈ {0}
   j ∈ {0}
   k ∈ {0}
   l ∈ {0}
-[eva] ilevel.i:24: Frama_C_show_each: {0; 1; 2; 3; 4; 6; 7; 8; 9}
+[eva] ilevel.c:30: Frama_C_show_each: {0; 1; 2; 3; 4; 6; 7; 8; 9}
 [eva] Recording results for main
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
 [eva:final-states] Values at end of function main:
   i ∈ {0; 1; 2; 3; 4; 5; 6; 7}
-  j ∈ {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16}
-  k ∈ {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15}
+  j ∈ [0..16]
+  k ∈ [0..15]
   l ∈ {0; 1; 2; 3; 4; 6; 7; 8; 9}
-  __retres ∈
-          {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18;
-           19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34;
-           35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47}
+  __retres ∈ [0..47]
diff --git a/tests/value/oracle/ilevel.1.res.oracle b/tests/value/oracle/ilevel.1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..af0704f7b5dc3605bcf5703ca05d7133098127fb
--- /dev/null
+++ b/tests/value/oracle/ilevel.1.res.oracle
@@ -0,0 +1,63 @@
+[kernel] Parsing ilevel.c (with preprocessing)
+[eva] Analyzing a complete application starting at large_ilevel
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  nondet ∈ [--..--]
+  i ∈ {0}
+  j ∈ {0}
+  k ∈ {0}
+  l ∈ {0}
+[eva] computing for function Frama_C_interval <- large_ilevel.
+  Called from ilevel.c:37.
+[eva] using specification for function Frama_C_interval
+[eva] ilevel.c:37: 
+  function Frama_C_interval: precondition 'order' got status valid.
+[eva] Done for function Frama_C_interval
+[eva] computing for function Frama_C_interval <- large_ilevel.
+  Called from ilevel.c:39.
+[eva] ilevel.c:39: 
+  function Frama_C_interval: precondition 'order' got status valid.
+[eva] Done for function Frama_C_interval
+[eva] Recording results for large_ilevel
+[eva] done for function large_ilevel
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function large_ilevel:
+  Frama_C_entropy_source ∈ [--..--]
+  i_0 ∈ [0..10]
+  j_0 ∈ [-25..-15] ∪ [0..10]
+  k_0 ∈ [100..200]
+  a[0] ∈ {53}
+   [1] ∈ {17}
+   [2] ∈ {64}
+   [3] ∈ {99}
+   [4] ∈ {25}
+   [5] ∈ {12}
+   [6] ∈ {72}
+   [7] ∈ {81}
+   [8] ∈ {404}
+   [9] ∈ {303}
+   [10] ∈ {-101}
+  s2 ∈ {40; 41; 42}
+  s1 ∈ {-101; 12; 17; 25; 53; 64; 72; 81; 99; 303; 404}
+  x ∈
+   {-101} ∪ [-25..-15] ∪ [0..10]
+    ∪ {12; 17; 25; 40; 41; 42; 53; 64; 72; 81} ∪ [99..127] ∪ [129..200]
+    ∪ {303; 404}
+[from] Computing for function large_ilevel
+[from] Computing for function Frama_C_interval <-large_ilevel
+[from] Done for function Frama_C_interval
+[from] Done for function large_ilevel
+[from] ====== DEPENDENCIES COMPUTED ======
+  These dependencies hold at termination for the executions that terminate:
+[from] Function Frama_C_interval:
+  Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF)
+  \result FROM Frama_C_entropy_source; min; max
+[from] Function large_ilevel:
+  Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF)
+[from] ====== END OF DEPENDENCIES ======
+[inout] Out (internal) for function large_ilevel:
+    Frama_C_entropy_source; i_0; j_0; tmp_0; k_0; a[0..10]; s2; tmp_2; 
+    tmp_3; s1; x; tmp_4; tmp_5; tmp_6
+[inout] Inputs for function large_ilevel:
+    Frama_C_entropy_source; nondet
diff --git a/tests/value/oracle/local_slevel.res.oracle b/tests/value/oracle/local_slevel.res.oracle
index ed3e146882954d10d8006e8bff555354f887b127..8dfd964a3ce6047ef3a8f0a901faa3d9209f784f 100644
--- a/tests/value/oracle/local_slevel.res.oracle
+++ b/tests/value/oracle/local_slevel.res.oracle
@@ -78,7 +78,7 @@
 [eva] local_slevel.i:37: Frama_C_show_each: {47}
 [eva] local_slevel.i:37: Frama_C_show_each: {48}
 [eva] local_slevel.i:37: Frama_C_show_each: {49}
-[eva] local_slevel.i:43: Trace partitioning superposing up to 100 states
+[eva] local_slevel.i:42: Trace partitioning superposing up to 100 states
 [eva] local_slevel.i:37: Frama_C_show_each: {50}
 [eva] local_slevel.i:37: Frama_C_show_each: {51}
 [eva] local_slevel.i:37: Frama_C_show_each: {52}
@@ -129,7 +129,7 @@
 [eva] local_slevel.i:37: Frama_C_show_each: {97}
 [eva] local_slevel.i:37: Frama_C_show_each: {98}
 [eva] local_slevel.i:37: Frama_C_show_each: {99}
-[eva] local_slevel.i:43: Trace partitioning superposing up to 200 states
+[eva] local_slevel.i:42: Trace partitioning superposing up to 200 states
 [eva] Recording results for main2
 [eva] Done for function main2
 [eva] Recording results for main
@@ -185,7 +185,7 @@ void main1(void)
     while (i < 80) {
       /*@ ensures \true;
           assigns v; */
-      /*@ slevel 50; */
+      /*@ slevel 50; */ ;
       if (i % 2) v = 1; else v = -1;
       Frama_C_show_each(v,i,r);
       v *= v;
@@ -251,7 +251,7 @@ void main1(void)
     while (i < 80) {
       /*@ ensures \true;
           assigns v; */
-      /*@ slevel 50; */
+      /*@ slevel 50; */ ;
       if (i % 2) v = 1; else v = -1;
       Frama_C_show_each(v,i,r);
       v *= v;
@@ -317,7 +317,7 @@ void main1(void)
     while (i < 80) {
       /*@ ensures \true;
           assigns v; */
-      /*@ slevel 50; */
+      /*@ slevel 50; */ ;
       if (i % 2) v = 1; else v = -1;
       Frama_C_show_each(v,i,r);
       v *= v;
@@ -446,7 +446,7 @@ void main(void)
 [eva] local_slevel.i:37: Frama_C_show_each: {47}
 [eva] local_slevel.i:37: Frama_C_show_each: {48}
 [eva] local_slevel.i:37: Frama_C_show_each: {49}
-[eva] local_slevel.i:43: Trace partitioning superposing up to 100 states
+[eva] local_slevel.i:42: Trace partitioning superposing up to 100 states
 [eva] local_slevel.i:37: Frama_C_show_each: {50}
 [eva] local_slevel.i:37: Frama_C_show_each: {51}
 [eva] local_slevel.i:37: Frama_C_show_each: {52}
@@ -497,7 +497,7 @@ void main(void)
 [eva] local_slevel.i:37: Frama_C_show_each: {97}
 [eva] local_slevel.i:37: Frama_C_show_each: {98}
 [eva] local_slevel.i:37: Frama_C_show_each: {99}
-[eva] local_slevel.i:43: Trace partitioning superposing up to 200 states
+[eva] local_slevel.i:42: Trace partitioning superposing up to 200 states
 [eva] Recording results for main2
 [eva] Done for function main2
 [eva] Recording results for main
diff --git a/tests/value/oracle/multidim.res.oracle b/tests/value/oracle/multidim.res.oracle
index 8b800aabbbee8ad467445cbf7bdab413b599d859..063652013480e6f05f3431090a10f35e00de62f9 100644
--- a/tests/value/oracle/multidim.res.oracle
+++ b/tests/value/oracle/multidim.res.oracle
@@ -186,7 +186,7 @@
   more than 1(1000) locations to update in array. Approximating.
 [eva] multidim.c:145: 
   Frama_C_domain_show_each:
-  t : # cvalue: [0].typ ∈ {1; 2} or UNINITIALIZED
+  t : # cvalue: [0].typ ∈ {INT; FLOAT} or UNINITIALIZED
                 {[0].val; [1..999]} ∈ [--..--] or UNINITIALIZED
       # multidim: [0 .. 999] = {
                     { .typ = {1}, .val.i = {42} } or 
@@ -250,7 +250,7 @@
   t[0..99] ∈ {0}
 [eva:final-states] Values at end of function main7:
   Frama_C_entropy_source ∈ [--..--]
-  t[0].typ ∈ {1; 2} or UNINITIALIZED
+  t[0].typ ∈ {INT; FLOAT} or UNINITIALIZED
    {[0].val; [1..999]} ∈ [--..--] or UNINITIALIZED
   j ∈ [0..999]
 [eva:final-states] Values at end of function main8:
diff --git a/tests/value/oracle/octagons-pointers-intermediate.res.oracle b/tests/value/oracle/octagons-pointers-intermediate.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..f6f6928d4db7af08f6ab5ce3c73d7c426302cd10
--- /dev/null
+++ b/tests/value/oracle/octagons-pointers-intermediate.res.oracle
@@ -0,0 +1,70 @@
+[kernel] Parsing octagons-pointers-intermediate.c (with preprocessing)
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  size ∈ {436}
+  buffer[0..435] ∈ {0}
+  nondet ∈ [--..--]
+[eva] computing for function init <- main.
+  Called from octagons-pointers-intermediate.c:38.
+[eva] octagons-pointers-intermediate.c:18: starting to merge loop iterations
+[eva] Recording results for init
+[eva] Done for function init
+[eva] computing for function cmdRead <- main.
+  Called from octagons-pointers-intermediate.c:45.
+[eva] Recording results for cmdRead
+[eva] Done for function cmdRead
+[eva] computing for function cmdRead <- main.
+  Called from octagons-pointers-intermediate.c:45.
+[eva] Recording results for cmdRead
+[eva] Done for function cmdRead
+[eva:loop-unroll:partial] octagons-pointers-intermediate.c:47: 
+  loop not completely unrolled
+[eva] Recording results for main
+[eva] done for function main
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function cmdRead:
+  len ∈ {{ &buffer + [3..433] }}
+  code ∈ {{ &buffer + [5..435] }}
+  elt1 ∈ {{ &buffer + [6..436] }}
+  elt2 ∈ {{ &buffer + [10..440] }}
+  elt3 ∈ {{ &buffer + [12..442] }}
+  c ∈ [--..--]
+  e1 ∈ [--..--]
+  e2 ∈ [--..--]
+  e3 ∈ [--..--]
+[eva:final-states] Values at end of function init:
+  buffer[0..435] ∈ [--..--]
+  i ∈ {436}
+[eva:final-states] Values at end of function main:
+  buffer[0..435] ∈ [--..--]
+  index ∈ [3..436]
+  cmd ∈ {{ &buffer + [3..436] }}
+[from] Computing for function cmdRead
+[from] Done for function cmdRead
+[from] Computing for function init
+[from] Done for function init
+[from] Computing for function main
+[from] Done for function main
+[from] ====== DEPENDENCIES COMPUTED ======
+  These dependencies hold at termination for the executions that terminate:
+[from] Function cmdRead:
+  NO EFFECTS
+[from] Function init:
+  buffer[0..435] FROM size; nondet (and SELF)
+[from] Function main:
+  buffer[0..435] FROM size; nondet (and SELF)
+[from] ====== END OF DEPENDENCIES ======
+[inout] Out (internal) for function cmdRead:
+    len; code; elt1; elt2; elt3; c; e1; e2; e3
+[inout] Inputs for function cmdRead:
+    buffer[5..435]
+[inout] Out (internal) for function init:
+    buffer[0..435]; i
+[inout] Inputs for function init:
+    size; nondet
+[inout] Out (internal) for function main:
+    buffer[0..435]; index; cmd
+[inout] Inputs for function main:
+    size; buffer[3..435]; nondet
diff --git a/tests/value/oracle/octagons-pointers-simple.res.oracle b/tests/value/oracle/octagons-pointers-simple.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..b4ac5a0756733ff58a4a12d5a53b72dca2edf3a6
--- /dev/null
+++ b/tests/value/oracle/octagons-pointers-simple.res.oracle
@@ -0,0 +1,87 @@
+[kernel] Parsing octagons-pointers-simple.c (with preprocessing)
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  size ∈ {436}
+  buffer[0..435] ∈ {0}
+  nondet ∈ [--..--]
+[eva] computing for function init <- main.
+  Called from octagons-pointers-simple.c:38.
+[eva] octagons-pointers-simple.c:18: starting to merge loop iterations
+[eva] Recording results for init
+[eva] Done for function init
+[eva] octagons-pointers-simple.c:46: 
+  Frama_C_dump_each:
+  # octagon:
+  {[ buffer - cmd ∈ {-3}
+     cmd->cmdLen - cmdLen ∈ {0}
+      ]}
+  ==END OF DUMP==
+[eva] computing for function cmdRead <- main.
+  Called from octagons-pointers-simple.c:47.
+[eva] Recording results for cmdRead
+[eva] Done for function cmdRead
+[eva] octagons-pointers-simple.c:46: 
+  Frama_C_dump_each:
+  # octagon:
+  {[ buffer - cmd ∈ [-436..-6]
+     cmd->cmdLen - cmdLen ∈ {0}
+     index + cmdLen ∈ [--..434]
+     cmd->cmdLen + index ∈ [--..434]
+      ]}
+  ==END OF DUMP==
+[eva] computing for function cmdRead <- main.
+  Called from octagons-pointers-simple.c:47.
+[eva] Recording results for cmdRead
+[eva] Done for function cmdRead
+[eva:loop-unroll:partial] octagons-pointers-simple.c:49: 
+  loop not completely unrolled
+[eva] Recording results for main
+[eva] done for function main
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function cmdRead:
+  len ∈ {{ &buffer + [3..433] }}
+  code ∈ {{ &buffer + [5..435] }}
+  elt1 ∈ {{ &buffer + [6..436] }}
+  elt2 ∈ {{ &buffer + [10..440] }}
+  elt3 ∈ {{ &buffer + [12..442] }}
+  c ∈ [--..--]
+  e1 ∈ [--..--]
+  e2 ∈ [--..--]
+  e3 ∈ [--..--]
+[eva:final-states] Values at end of function init:
+  buffer[0..435] ∈ [--..--]
+  i ∈ {436}
+[eva:final-states] Values at end of function main:
+  buffer[0..435] ∈ [--..--]
+  index ∈ [3..436]
+  cmdLen ∈ [0..65535]
+  cmd ∈ {{ &buffer + [3..436] }}
+[from] Computing for function cmdRead
+[from] Done for function cmdRead
+[from] Computing for function init
+[from] Done for function init
+[from] Computing for function main
+[from] Done for function main
+[from] ====== DEPENDENCIES COMPUTED ======
+  These dependencies hold at termination for the executions that terminate:
+[from] Function cmdRead:
+  NO EFFECTS
+[from] Function init:
+  buffer[0..435] FROM size; nondet (and SELF)
+[from] Function main:
+  buffer[0..435] FROM size; nondet (and SELF)
+[from] ====== END OF DEPENDENCIES ======
+[inout] Out (internal) for function cmdRead:
+    len; code; elt1; elt2; elt3; c; e1; e2; e3
+[inout] Inputs for function cmdRead:
+    buffer[5..435]
+[inout] Out (internal) for function init:
+    buffer[0..435]; i
+[inout] Inputs for function init:
+    size; nondet
+[inout] Out (internal) for function main:
+    buffer[0..435]; index; cmdLen; cmd
+[inout] Inputs for function main:
+    size; buffer[3..435]; nondet
diff --git a/tests/value/oracle/octagons-pointers.res.oracle b/tests/value/oracle/octagons-pointers.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..dcc4c9fa9e70f408240e63200520b112956ebb1c
--- /dev/null
+++ b/tests/value/oracle/octagons-pointers.res.oracle
@@ -0,0 +1,130 @@
+[kernel] Parsing octagons-pointers.c (with preprocessing)
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  size ∈ {436}
+  buffer[0..435] ∈ {0}
+  nondet ∈ [--..--]
+[eva] computing for function init <- main.
+  Called from octagons-pointers.c:39.
+[eva] octagons-pointers.c:18: starting to merge loop iterations
+[eva] Recording results for init
+[eva] Done for function init
+[eva] octagons-pointers.c:46: 
+  Frama_C_dump_each:
+  # octagon:
+  {[ buffer - cmd ∈ {-3}
+      ]}
+  ==END OF DUMP==
+[eva] computing for function cmdRead <- main.
+  Called from octagons-pointers.c:47.
+[eva] octagons-pointers.c:31: 
+  Frama_C_dump_each:
+  # octagon:
+  {[ buffer - cmd ∈ {-3}
+     buffer - cmd ∈ {-3}
+     cmd - cmd ∈ {0}
+      ]}
+  ==END OF DUMP==
+[eva] Recording results for cmdRead
+[eva] Done for function cmdRead
+[eva] octagons-pointers.c:46: 
+  Frama_C_dump_each:
+  # octagon:
+  {[ buffer - cmd ∈ [-436..-6]
+     cmd->cmdLen + index ∈ [--..434]
+      ]}
+  ==END OF DUMP==
+[eva] computing for function cmdRead <- main.
+  Called from octagons-pointers.c:47.
+[eva] octagons-pointers.c:31: 
+  Frama_C_dump_each:
+  # octagon:
+  {[ buffer - cmd ∈ [-436..-6]
+     buffer - cmd ∈ [-433..-6]
+     cmd - cmd ∈ [-430..427]
+     cmd->cmdLen + index ∈ [--..434]
+     cmd - len ∈ {0}
+     buffer - len ∈ [-433..-6]
+     len - cmd ∈ [-430..427]
+     len - code ∈ {-2}
+     buffer - code ∈ [-435..-8]
+     cmd - code ∈ {-2}
+     code - cmd ∈ [-428..429]
+     code - elt1 ∈ {-1}
+     buffer - elt1 ∈ [-436..-9]
+     cmd - elt1 ∈ {-3}
+     len - elt1 ∈ {-3}
+     elt1 - cmd ∈ [-427..430]
+     elt1 - elt2 ∈ {-4}
+     buffer - elt2 ∈ [-440..-13]
+     cmd - elt2 ∈ {-7}
+     len - elt2 ∈ {-7}
+     code - elt2 ∈ {-5}
+     elt2 - cmd ∈ [-423..434]
+     elt2 - elt3 ∈ {-2}
+     buffer - elt3 ∈ [-442..-15]
+     cmd - elt3 ∈ {-9}
+     len - elt3 ∈ {-9}
+     code - elt3 ∈ {-7}
+     elt1 - elt3 ∈ {-6}
+     elt3 - cmd ∈ [-421..436]
+      ]}
+  ==END OF DUMP==
+[eva:alarm] octagons-pointers.c:33: Warning: 
+  out of bounds read. assert \valid_read(elt1);
+[eva:alarm] octagons-pointers.c:34: Warning: 
+  out of bounds read. assert \valid_read(elt2);
+[eva:alarm] octagons-pointers.c:35: Warning: 
+  out of bounds read. assert \valid_read(elt3);
+[eva] Recording results for cmdRead
+[eva] Done for function cmdRead
+[eva:loop-unroll:partial] octagons-pointers.c:49: loop not completely unrolled
+[eva] Recording results for main
+[eva] done for function main
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function cmdRead:
+  len ∈ {{ &buffer + [3..433] }}
+  code ∈ {{ &buffer + [5..435] }}
+  elt1 ∈ {{ &buffer + [6..436] }}
+  elt2 ∈ {{ &buffer + [10..440] }}
+  elt3 ∈ {{ &buffer + [12..442] }}
+  c ∈ [--..--]
+  e1 ∈ [--..--]
+  e2 ∈ [--..--]
+  e3 ∈ [--..--]
+[eva:final-states] Values at end of function init:
+  buffer[0..435] ∈ [--..--]
+  i ∈ {436}
+[eva:final-states] Values at end of function main:
+  buffer[0..435] ∈ [--..--]
+  index ∈ [3..436]
+  cmd ∈ {{ &buffer + [3..436] }}
+[from] Computing for function cmdRead
+[from] Done for function cmdRead
+[from] Computing for function init
+[from] Done for function init
+[from] Computing for function main
+[from] Done for function main
+[from] ====== DEPENDENCIES COMPUTED ======
+  These dependencies hold at termination for the executions that terminate:
+[from] Function cmdRead:
+  NO EFFECTS
+[from] Function init:
+  buffer[0..435] FROM size; nondet (and SELF)
+[from] Function main:
+  buffer[0..435] FROM size; nondet (and SELF)
+[from] ====== END OF DEPENDENCIES ======
+[inout] Out (internal) for function cmdRead:
+    len; code; elt1; elt2; elt3; c; e1; e2; e3
+[inout] Inputs for function cmdRead:
+    buffer[3..435]
+[inout] Out (internal) for function init:
+    buffer[0..435]; i
+[inout] Inputs for function init:
+    size; nondet
+[inout] Out (internal) for function main:
+    buffer[0..435]; index; cmd
+[inout] Inputs for function main:
+    size; buffer[3..435]; nondet
diff --git a/tests/value/oracle/octagons.res.oracle b/tests/value/oracle/octagons.res.oracle
index 9a12d8aaa3b350f6a15641bb6783d1636521ec2b..918911acb43c4f0d2111992d756dee96b8782448 100644
--- a/tests/value/oracle/octagons.res.oracle
+++ b/tests/value/oracle/octagons.res.oracle
@@ -218,7 +218,10 @@
   Called from octagons.c:196.
 [eva] Recording results for neg
 [eva] Done for function neg
-[eva] octagons.c:197: Reusing old results for call to neg
+[eva] computing for function neg <- interprocedural <- main.
+  Called from octagons.c:197.
+[eva] Recording results for neg
+[eva] Done for function neg
 [eva] computing for function diff <- interprocedural <- main.
   Called from octagons.c:206.
 [eva] Recording results for diff
@@ -235,6 +238,8 @@
   # octagon:
   {[ a + neg_a ∈ {0}
      b + neg_b ∈ {0}
+     p - a ∈ {0}
+     *p - a1 ∈ {0}
       ]}
   ==END OF DUMP==
 [eva] Recording results for test_non_integer_args
diff --git a/tests/value/oracle/partitioning-annots.0.res.oracle b/tests/value/oracle/partitioning-annots.0.res.oracle
index ef583a47f12fc77c9189539ef61777c459342e78..aa52873360db70044e939172e2cff1a5bba13fdb 100644
--- a/tests/value/oracle/partitioning-annots.0.res.oracle
+++ b/tests/value/oracle/partitioning-annots.0.res.oracle
@@ -6,13 +6,13 @@
   nondet ∈ [--..--]
   k ∈ {0}
 [eva] computing for function test_slevel <- main.
-  Called from partitioning-annots.c:223.
-[eva] partitioning-annots.c:188: starting to merge loop iterations
-[eva] partitioning-annots.c:193: starting to merge loop iterations
+  Called from partitioning-annots.c:278.
+[eva] partitioning-annots.c:243: starting to merge loop iterations
+[eva] partitioning-annots.c:248: starting to merge loop iterations
 [eva] Recording results for test_slevel
 [eva] Done for function test_slevel
 [eva] computing for function test_unroll <- main.
-  Called from partitioning-annots.c:224.
+  Called from partitioning-annots.c:279.
 [eva:loop-unroll:partial] partitioning-annots.c:26: loop not completely unrolled
 [eva] partitioning-annots.c:26: starting to merge loop iterations
 [eva:loop-unroll:partial] partitioning-annots.c:34: loop not completely unrolled
@@ -25,7 +25,7 @@
 [eva] Recording results for test_unroll
 [eva] Done for function test_unroll
 [eva] computing for function test_split <- main.
-  Called from partitioning-annots.c:225.
+  Called from partitioning-annots.c:280.
 [eva] computing for function Frama_C_interval <- test_split <- main.
   Called from partitioning-annots.c:73.
 [eva] using specification for function Frama_C_interval
@@ -65,7 +65,7 @@
 [eva] Recording results for test_split
 [eva] Done for function test_split
 [eva] computing for function test_dynamic_split <- main.
-  Called from partitioning-annots.c:226.
+  Called from partitioning-annots.c:281.
 [eva] partitioning-annots.c:95: Warning: 
   this partitioning parameter cannot be evaluated safely on all states
 [eva] computing for function Frama_C_interval <- test_dynamic_split <- main.
@@ -90,13 +90,44 @@
 [eva] Recording results for test_dynamic_split
 [eva] Done for function test_dynamic_split
 [eva] computing for function test_dynamic_split_predicate <- main.
-  Called from partitioning-annots.c:227.
+  Called from partitioning-annots.c:282.
 [eva] partitioning-annots.c:124: starting to merge loop iterations
 [eva] Recording results for test_dynamic_split_predicate
 [eva] Done for function test_dynamic_split_predicate
+[eva] computing for function test_splits_post_call <- main.
+  Called from partitioning-annots.c:283.
+[eva] computing for function Frama_C_interval <- test_splits_post_call <- main.
+  Called from partitioning-annots.c:205.
+[eva] partitioning-annots.c:205: 
+  function Frama_C_interval: precondition 'order' got status valid.
+[eva] Done for function Frama_C_interval
+[eva] computing for function spec <- test_splits_post_call <- main.
+  Called from partitioning-annots.c:206.
+[eva] using specification for function spec
+[eva] Done for function spec
+[eva] partitioning-annots.c:211: Frama_C_show_each_spec: [-2147483648..-10], ⊥
+[eva] partitioning-annots.c:211: Frama_C_show_each_spec: [10..2147483647], ⊥
+[eva] partitioning-annots.c:211: Frama_C_show_each_spec: {-1}, [-1000..1000]
+[eva] computing for function body <- test_splits_post_call <- main.
+  Called from partitioning-annots.c:212.
+[eva] Recording results for body
+[eva] Done for function body
+[eva] partitioning-annots.c:212: Reusing old results for call to body
+[eva] partitioning-annots.c:212: Reusing old results for call to body
+[eva] partitioning-annots.c:217: Frama_C_show_each_body: [-510..-10], ⊥
+[eva] partitioning-annots.c:217: Frama_C_show_each_body: [10..510], ⊥
+[eva] partitioning-annots.c:217: Frama_C_show_each_body: {-1}, [-1000..1000]
+[eva] Recording results for test_splits_post_call
+[eva] Done for function test_splits_post_call
 [eva] Recording results for main
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function body:
+  i2 ∈ [-500..500]
+  absolute ∈ [0..500]
+  state ∈ {-1; 0; 1}
+  y ∈ [-1000..1000] or UNINITIALIZED
+  __retres ∈ [-510..510]
 [eva:final-states] Values at end of function test_dynamic_split:
   Frama_C_entropy_source ∈ [--..--]
   a ∈ {0}
@@ -117,6 +148,13 @@
   k ∈ {0; 1}
   i ∈ {0; 1}
   j ∈ {0; 1; 2}
+[eva:final-states] Values at end of function test_splits_post_call:
+  Frama_C_entropy_source ∈ [--..--]
+  x ∈ [-1000..1000] or UNINITIALIZED
+  y ∈ [-1000..1000] or UNINITIALIZED
+  error ∈ [-1000..1000] or UNINITIALIZED
+  i ∈ [-1000..1000]
+  r ∈ [-510..510]
 [eva:final-states] Values at end of function test_unroll:
   a[0..9] ∈ {42}
   b[0..9] ∈ {42}
@@ -145,6 +183,8 @@
 [eva:final-states] Values at end of function main:
   Frama_C_entropy_source ∈ [--..--]
   k ∈ {0; 1}
+[from] Computing for function body
+[from] Done for function body
 [from] Computing for function test_dynamic_split
 [from] Computing for function Frama_C_interval <-test_dynamic_split
 [from] Done for function Frama_C_interval
@@ -155,6 +195,10 @@
 [from] Done for function test_slevel
 [from] Computing for function test_split
 [from] Done for function test_split
+[from] Computing for function test_splits_post_call
+[from] Computing for function spec <-test_splits_post_call
+[from] Done for function spec
+[from] Done for function test_splits_post_call
 [from] Computing for function test_unroll
 [from] Done for function test_unroll
 [from] Computing for function main
@@ -164,6 +208,12 @@
 [from] Function Frama_C_interval:
   Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF)
   \result FROM Frama_C_entropy_source; min; max
+[from] Function body:
+  y FROM nondet; i; p (and SELF)
+  \result FROM nondet; i
+[from] Function spec:
+  x FROM i
+  \result FROM i
 [from] Function test_dynamic_split:
   Frama_C_entropy_source FROM Frama_C_entropy_source; nondet (and SELF)
 [from] Function test_dynamic_split_predicate:
@@ -173,12 +223,18 @@
 [from] Function test_split:
   Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF)
   k FROM Frama_C_entropy_source
+[from] Function test_splits_post_call:
+  Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF)
 [from] Function test_unroll:
   NO EFFECTS
 [from] Function main:
   Frama_C_entropy_source FROM Frama_C_entropy_source; nondet (and SELF)
   k FROM Frama_C_entropy_source
 [from] ====== END OF DEPENDENCIES ======
+[inout] Out (internal) for function body:
+    i2; absolute; tmp; state; y; __retres
+[inout] Inputs for function body:
+    nondet
 [inout] Out (internal) for function test_dynamic_split:
     Frama_C_entropy_source; a; b
 [inout] Inputs for function test_dynamic_split:
@@ -195,6 +251,10 @@
     Frama_C_entropy_source; k; i; j
 [inout] Inputs for function test_split:
     Frama_C_entropy_source; k
+[inout] Out (internal) for function test_splits_post_call:
+    Frama_C_entropy_source; x; y; error; i; r
+[inout] Inputs for function test_splits_post_call:
+    Frama_C_entropy_source; nondet
 [inout] Out (internal) for function test_unroll:
     a[0..9]; b[0..9]; c[0..19]; d[0..19]; e[0..9]; i; j; i_0; j_0; i_1; 
     i_2; i_3; j_1
diff --git a/tests/value/oracle/partitioning-annots.3.res.oracle b/tests/value/oracle/partitioning-annots.3.res.oracle
index 3fe49f8ff9266240c18aac21e67f32978e3992ca..365ff709693100a98812f0b3ee71f2608624ab07 100644
--- a/tests/value/oracle/partitioning-annots.3.res.oracle
+++ b/tests/value/oracle/partitioning-annots.3.res.oracle
@@ -6,13 +6,13 @@
   nondet ∈ [--..--]
   k ∈ {0}
 [eva] computing for function Frama_C_interval <- test_history.
-  Called from partitioning-annots.c:167.
+  Called from partitioning-annots.c:222.
 [eva] using specification for function Frama_C_interval
-[eva] partitioning-annots.c:167: 
+[eva] partitioning-annots.c:222: 
   function Frama_C_interval: precondition 'order' got status valid.
 [eva] Done for function Frama_C_interval
-[eva] partitioning-annots.c:173: Frama_C_show_each: {0; 1}, {0; 1}
-[eva:alarm] partitioning-annots.c:176: Warning: 
+[eva] partitioning-annots.c:228: Frama_C_show_each: {0; 1}, {0; 1}
+[eva:alarm] partitioning-annots.c:231: Warning: 
   division by zero. assert j ≢ 0;
 [eva] Recording results for test_history
 [eva] done for function test_history
diff --git a/tests/value/oracle/partitioning-annots.4.res.oracle b/tests/value/oracle/partitioning-annots.4.res.oracle
index 793324f2603cfd3fb554a92a29803c88ae31e867..8ad2cdfc8afe43036525234351b1a5baebfff62c 100644
--- a/tests/value/oracle/partitioning-annots.4.res.oracle
+++ b/tests/value/oracle/partitioning-annots.4.res.oracle
@@ -6,13 +6,13 @@
   nondet ∈ [--..--]
   k ∈ {0}
 [eva] computing for function Frama_C_interval <- test_history.
-  Called from partitioning-annots.c:167.
+  Called from partitioning-annots.c:222.
 [eva] using specification for function Frama_C_interval
-[eva] partitioning-annots.c:167: 
+[eva] partitioning-annots.c:222: 
   function Frama_C_interval: precondition 'order' got status valid.
 [eva] Done for function Frama_C_interval
-[eva] partitioning-annots.c:173: Frama_C_show_each: {0}, {0}
-[eva] partitioning-annots.c:173: Frama_C_show_each: {1}, {1}
+[eva] partitioning-annots.c:228: Frama_C_show_each: {0}, {0}
+[eva] partitioning-annots.c:228: Frama_C_show_each: {1}, {1}
 [eva] Recording results for test_history
 [eva] done for function test_history
 [eva] ====== VALUES COMPUTED ======
diff --git a/tests/value/oracle/recol.1.res.oracle b/tests/value/oracle/recol.1.res.oracle
index 89f1f21dd124e2d9ebfc2e09cc6ccec64f318aa4..23eb96edca7dc95f69bc4907078beeec131dfea0 100644
--- a/tests/value/oracle/recol.1.res.oracle
+++ b/tests/value/oracle/recol.1.res.oracle
@@ -23,10 +23,10 @@
 [eva:final-states] Values at end of function main:
   s[bits 0 to 15] ∈ {97}
    [bits 16 to 47] ∈ {776}
-   [6] ∈ {-103}
+   [6] ∈ {153}
    [bits 56 to 71] ∈ {-26736}
    [bits 72 to 103] ∈ {271697}
-   [13] ∈ {-104}
+   [13] ∈ {152}
    [bits 112 to 127] ∈ {10121}
    [bits 128 to 159] ∈ {93197600}
    [20] ∈ {65}
@@ -52,8 +52,8 @@
    [bits 552 to 583] ∈ {1373000945}
    [bits 584 to 599] ∈ {21240}
    [75] ∈ {41}
-   [76] ∈ {-128}
-   [77] ∈ {-31}
+   [76] ∈ {128}
+   [77] ∈ {225}
    [bits 624 to 655] ∈ {-832127096}
    [82] ∈ {25}
    [83] ∈ {16}
diff --git a/tests/value/oracle/statistics.csv b/tests/value/oracle/statistics.csv
new file mode 100644
index 0000000000000000000000000000000000000000..f844aeb8ca15700b2e9b58fd5303876925a37bae
--- /dev/null
+++ b/tests/value/oracle/statistics.csv
@@ -0,0 +1,7 @@
+memexec-hits	g		3
+memexec-misses	g		5
+memexec-misses	f		2
+memexec-misses	main		1
+partitioning-index-misses			57
+max-widenings	f	statistics.i:12	1
+iterations	f	statistics.i:12	8
diff --git a/tests/value/oracle/statistics.res.oracle b/tests/value/oracle/statistics.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..9d6258ee598876f6071ef856f29e7393a2de4ab0
--- /dev/null
+++ b/tests/value/oracle/statistics.res.oracle
@@ -0,0 +1,76 @@
+[kernel] Parsing statistics.i (no preprocessing)
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  
+[eva] computing for function f <- main.
+  Called from statistics.i:18.
+[eva] computing for function g <- f <- main.
+  Called from statistics.i:13.
+[eva] Recording results for g
+[eva] Done for function g
+[eva] statistics.i:12: starting to merge loop iterations
+[eva] computing for function g <- f <- main.
+  Called from statistics.i:13.
+[eva] Recording results for g
+[eva] Done for function g
+[eva] computing for function g <- f <- main.
+  Called from statistics.i:13.
+[eva] Recording results for g
+[eva] Done for function g
+[eva] computing for function g <- f <- main.
+  Called from statistics.i:13.
+[eva] Recording results for g
+[eva] Done for function g
+[eva] Recording results for f
+[eva] Done for function f
+[eva:alarm] statistics.i:19: Warning: 
+  signed overflow. assert -2147483648 ≤ n - 1;
+[eva] computing for function f <- main.
+  Called from statistics.i:19.
+[eva] statistics.i:13: Reusing old results for call to g
+[eva] statistics.i:13: Reusing old results for call to g
+[eva] statistics.i:13: Reusing old results for call to g
+[eva] computing for function g <- f <- main.
+  Called from statistics.i:13.
+[eva] Recording results for g
+[eva] Done for function g
+[eva] Recording results for f
+[eva] Done for function f
+[eva] Recording results for main
+[eva] done for function main
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function g:
+  
+[eva:final-states] Values at end of function f:
+  i ∈ [0..2147483647]
+[eva:final-states] Values at end of function main:
+  __retres ∈ {0}
+[from] Computing for function g
+[from] Done for function g
+[from] Computing for function f
+[from] Done for function f
+[from] Computing for function main
+[from] Done for function main
+[from] ====== DEPENDENCIES COMPUTED ======
+  These dependencies hold at termination for the executions that terminate:
+[from] Function g:
+  NO EFFECTS
+[from] Function f:
+  NO EFFECTS
+[from] Function main:
+  \result FROM \nothing
+[from] ====== END OF DEPENDENCIES ======
+[inout] Out (internal) for function g:
+    \nothing
+[inout] Inputs for function g:
+    \nothing
+[inout] Out (internal) for function f:
+    i
+[inout] Inputs for function f:
+    \nothing
+[inout] Out (internal) for function main:
+    __retres
+[inout] Inputs for function main:
+    \nothing
diff --git a/tests/value/oracle/strucval.res.oracle b/tests/value/oracle/strucval.res.oracle
index 908dd3c2c463501d61052957b91ce73ca43c9f66..b6030c1596582d9bf85a600b83ccd3db16ca24a8 100644
--- a/tests/value/oracle/strucval.res.oracle
+++ b/tests/value/oracle/strucval.res.oracle
@@ -12,7 +12,7 @@
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
 [eva:final-states] Values at end of function main:
-  SharedData.FunctionCode ∈ {0}
+  SharedData.FunctionCode ∈ {BDP_BITE_NORMAL}
             .MachineNumber ∈ {1456}
             .[bits 48 to 63] ∈ UNINITIALIZED
             .Line ∈ {25}
diff --git a/tests/value/oracle_apron/octagons-pointers-simple.res.oracle b/tests/value/oracle_apron/octagons-pointers-simple.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..c976f8080e08fd8a1562ddb133889ddac757a32f
--- /dev/null
+++ b/tests/value/oracle_apron/octagons-pointers-simple.res.oracle
@@ -0,0 +1,15 @@
+39a40,53
+> [eva] octagons-pointers-simple.c:43: starting to merge loop iterations
+> [eva] octagons-pointers-simple.c:46: 
+>   Frama_C_dump_each:
+>   # octagon:
+>   {[ buffer - cmd ∈ [-436..-6]
+>      cmd->cmdLen - cmdLen ∈ {0}
+>      index + cmdLen ∈ [--..434]
+>      cmd->cmdLen + index ∈ [--..434]
+>       ]}
+>   ==END OF DUMP==
+> [eva] computing for function cmdRead <- main.
+>   Called from octagons-pointers-simple.c:47.
+> [eva] Recording results for cmdRead
+> [eva] Done for function cmdRead
diff --git a/tests/value/oracle_apron/octagons.res.oracle b/tests/value/oracle_apron/octagons.res.oracle
index b6259b0a61145df421dce827edfc493473abffca..1c3d249968164cc4519adfbf3661a2bbabe3a944 100644
--- a/tests/value/oracle_apron/octagons.res.oracle
+++ b/tests/value/oracle_apron/octagons.res.oracle
@@ -1,16 +1,4 @@
-221c221,224
-< [eva] octagons.c:197: Reusing old results for call to neg
----
-> [eva] computing for function neg <- interprocedural <- main.
->   Called from octagons.c:197.
-> [eva] Recording results for neg
-> [eva] Done for function neg
-237a241,244
->      a - b ∈ [-16..16]
->      b + neg_a ∈ [-16..16]
->      a + neg_b ∈ [-16..16]
->      neg_a - neg_b ∈ [-16..16]
-366,369c373,376
+371,374c371,374
 <   a ∈ [-1024..2147483647]
 <   b ∈ [-1023..2147483647]
 <   c ∈ [-1023..2147483647]
diff --git a/tests/value/oracle_apron/partitioning-annots.0.res.oracle b/tests/value/oracle_apron/partitioning-annots.0.res.oracle
index 94ed9ffca14931983ca8b0fcfd773dae01006fe7..68d268103b83832bb45759df2b7108b8ad474e1e 100644
--- a/tests/value/oracle_apron/partitioning-annots.0.res.oracle
+++ b/tests/value/oracle_apron/partitioning-annots.0.res.oracle
@@ -1,4 +1,16 @@
-105,106c105,106
+115,116c115,122
+< [eva] partitioning-annots.c:212: Reusing old results for call to body
+< [eva] partitioning-annots.c:212: Reusing old results for call to body
+---
+> [eva] computing for function body <- test_splits_post_call <- main.
+>   Called from partitioning-annots.c:212.
+> [eva] Recording results for body
+> [eva] Done for function body
+> [eva] computing for function body <- test_splits_post_call <- main.
+>   Called from partitioning-annots.c:212.
+> [eva] Recording results for body
+> [eva] Done for function body
+136,137c142,143
 <   x ∈ [0..44]
 <   y ∈ [0..44]
 ---
diff --git a/tests/value/oracle_apron/partitioning-annots.3.res.oracle b/tests/value/oracle_apron/partitioning-annots.3.res.oracle
index d04cebfc945498812ebf2de1f658c5458442d6d8..5a8823d8cc9e5c5d07f57720b06f7c0917f9c17a 100644
--- a/tests/value/oracle_apron/partitioning-annots.3.res.oracle
+++ b/tests/value/oracle_apron/partitioning-annots.3.res.oracle
@@ -1,3 +1,3 @@
 15,16d14
-< [eva:alarm] partitioning-annots.c:176: Warning: 
+< [eva:alarm] partitioning-annots.c:231: Warning: 
 <   division by zero. assert j ≢ 0;
diff --git a/tests/value/oracle_apron/statistics.res.oracle b/tests/value/oracle_apron/statistics.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..9a97de5637c3ca83fe4c2b5547eb7e2616f9bf94
--- /dev/null
+++ b/tests/value/oracle_apron/statistics.res.oracle
@@ -0,0 +1,17 @@
+32,34c32,43
+< [eva] statistics.i:13: Reusing old results for call to g
+< [eva] statistics.i:13: Reusing old results for call to g
+< [eva] statistics.i:13: Reusing old results for call to g
+---
+> [eva] computing for function g <- f <- main.
+>   Called from statistics.i:13.
+> [eva] Recording results for g
+> [eva] Done for function g
+> [eva] computing for function g <- f <- main.
+>   Called from statistics.i:13.
+> [eva] Recording results for g
+> [eva] Done for function g
+> [eva] computing for function g <- f <- main.
+>   Called from statistics.i:13.
+> [eva] Recording results for g
+> [eva] Done for function g
diff --git a/tests/value/oracle_equality/octagons.res.oracle b/tests/value/oracle_equality/octagons.res.oracle
index bf4e1ca8d51e0aaa4c7ec1117686a0c8ee9807b4..3b1ca3ecba8569890b9c9fad8a1d7fe77e4b0226 100644
--- a/tests/value/oracle_equality/octagons.res.oracle
+++ b/tests/value/oracle_equality/octagons.res.oracle
@@ -2,18 +2,7 @@
 < [eva] octagons.c:54: Frama_C_show_each_unreduced_char: [-128..127], [-128..127]
 ---
 > [eva] octagons.c:54: Frama_C_show_each_unreduced_char: [-118..114], [6..127]
-221c221,224
-< [eva] octagons.c:197: Reusing old results for call to neg
----
-> [eva] computing for function neg <- interprocedural <- main.
->   Called from octagons.c:197.
-> [eva] Recording results for neg
-> [eva] Done for function neg
-237a241,243
->      a - b ∈ [-16..16]
->      b + neg_a ∈ [-16..16]
->      a + neg_b ∈ [-16..16]
-353c359
+358c358
 <   ct ∈ [--..--] or UNINITIALIZED
 ---
 >   ct ∈ [6..127] or UNINITIALIZED
diff --git a/tests/value/oracle_gauges/gauges.res.oracle b/tests/value/oracle_gauges/gauges.res.oracle
index bd0f8dbd9eb7433da20ad4403a92494bb6396cb2..89bba971700e381aecb42f0a87e0010a27a5a7d7 100644
--- a/tests/value/oracle_gauges/gauges.res.oracle
+++ b/tests/value/oracle_gauges/gauges.res.oracle
@@ -135,7 +135,7 @@
 >   # cvalue:
 >   __fc_heap_status ∈ [--..--]
 >   __fc_random_counter ∈ [--..--]
->   __fc_rand_max ∈ {32767}
+>   __fc_rand_max ∈ {2147483647}
 >   __fc_random48_init ∈ {0}
 >   __fc_random48_counter[0..2] ∈ [--..--]
 >   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
@@ -199,7 +199,7 @@
 >   # cvalue:
 >   __fc_heap_status ∈ [--..--]
 >   __fc_random_counter ∈ [--..--]
->   __fc_rand_max ∈ {32767}
+>   __fc_rand_max ∈ {2147483647}
 >   __fc_random48_init ∈ {0}
 >   __fc_random48_counter[0..2] ∈ [--..--]
 >   __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }}
diff --git a/tests/value/oracle_gauges/octagons-pointers-intermediate.res.oracle b/tests/value/oracle_gauges/octagons-pointers-intermediate.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..993825158c77e1d611c02be27e37da1414ab72d1
--- /dev/null
+++ b/tests/value/oracle_gauges/octagons-pointers-intermediate.res.oracle
@@ -0,0 +1,8 @@
+23a24,30
+> [eva] octagons-pointers-intermediate.c:42: starting to merge loop iterations
+> [eva] octagons-pointers-intermediate.c:45: 
+>   Reusing old results for call to cmdRead
+> [eva] octagons-pointers-intermediate.c:45: 
+>   Reusing old results for call to cmdRead
+> [eva] octagons-pointers-intermediate.c:45: 
+>   Reusing old results for call to cmdRead
diff --git a/tests/value/oracle_gauges/octagons-pointers-simple.res.oracle b/tests/value/oracle_gauges/octagons-pointers-simple.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..1f0784eedc6dda45bb7958cdb87c4a3553ffd9b4
--- /dev/null
+++ b/tests/value/oracle_gauges/octagons-pointers-simple.res.oracle
@@ -0,0 +1,32 @@
+39a40,70
+> [eva] octagons-pointers-simple.c:43: starting to merge loop iterations
+> [eva] octagons-pointers-simple.c:46: 
+>   Frama_C_dump_each:
+>   # octagon:
+>   {[ buffer - cmd ∈ [-436..-6]
+>      cmd->cmdLen - cmdLen ∈ {0}
+>      index + cmdLen ∈ [--..434]
+>      cmd->cmdLen + index ∈ [--..434]
+>       ]}
+>   ==END OF DUMP==
+> [eva] octagons-pointers-simple.c:47: Reusing old results for call to cmdRead
+> [eva] octagons-pointers-simple.c:46: 
+>   Frama_C_dump_each:
+>   # octagon:
+>   {[ buffer - cmd ∈ [-436..-6]
+>      cmd->cmdLen - cmdLen ∈ {0}
+>      index + cmdLen ∈ [--..434]
+>      cmd->cmdLen + index ∈ [--..434]
+>       ]}
+>   ==END OF DUMP==
+> [eva] octagons-pointers-simple.c:47: Reusing old results for call to cmdRead
+> [eva] octagons-pointers-simple.c:46: 
+>   Frama_C_dump_each:
+>   # octagon:
+>   {[ buffer - cmd ∈ [-436..-6]
+>      cmd->cmdLen - cmdLen ∈ {0}
+>      index + cmdLen ∈ [--..434]
+>      cmd->cmdLen + index ∈ [--..434]
+>       ]}
+>   ==END OF DUMP==
+> [eva] octagons-pointers-simple.c:47: Reusing old results for call to cmdRead
diff --git a/tests/value/oracle_gauges/octagons-pointers.res.oracle b/tests/value/oracle_gauges/octagons-pointers.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..2c58a7bd206f37b42c9c11cda6d577546e1498e6
--- /dev/null
+++ b/tests/value/oracle_gauges/octagons-pointers.res.oracle
@@ -0,0 +1,26 @@
+83a84,108
+> [eva] octagons-pointers.c:43: starting to merge loop iterations
+> [eva] octagons-pointers.c:46: 
+>   Frama_C_dump_each:
+>   # octagon:
+>   {[ buffer - cmd ∈ [-436..-6]
+>      cmd->cmdLen + index ∈ [--..434]
+>       ]}
+>   ==END OF DUMP==
+> [eva] octagons-pointers.c:47: Reusing old results for call to cmdRead
+> [eva] octagons-pointers.c:46: 
+>   Frama_C_dump_each:
+>   # octagon:
+>   {[ buffer - cmd ∈ [-436..-6]
+>      cmd->cmdLen + index ∈ [--..434]
+>       ]}
+>   ==END OF DUMP==
+> [eva] octagons-pointers.c:47: Reusing old results for call to cmdRead
+> [eva] octagons-pointers.c:46: 
+>   Frama_C_dump_each:
+>   # octagon:
+>   {[ buffer - cmd ∈ [-436..-6]
+>      cmd->cmdLen + index ∈ [--..434]
+>       ]}
+>   ==END OF DUMP==
+> [eva] octagons-pointers.c:47: Reusing old results for call to cmdRead
diff --git a/tests/value/oracle_gauges/octagons.res.oracle b/tests/value/oracle_gauges/octagons.res.oracle
index 877c9b13068e01e847619bf42b92f3873f3fcb0e..f07f5b7d9bc184727b1db9fd272ec66d12fae701 100644
--- a/tests/value/oracle_gauges/octagons.res.oracle
+++ b/tests/value/oracle_gauges/octagons.res.oracle
@@ -11,7 +11,7 @@
 < [eva] octagons.c:143: Frama_C_show_each_imprecise: [-2147483648..1]
 ---
 > [eva] octagons.c:143: Frama_C_show_each_imprecise: [-2468..1]
-366,369c358,361
+371,374c363,366
 <   a ∈ [-1024..2147483647]
 <   b ∈ [-1023..2147483647]
 <   c ∈ [-1023..2147483647]
@@ -21,7 +21,7 @@
 >   b ∈ [-181..1867]
 >   c ∈ [-602..1446]
 >   d ∈ [-190..1874]
-371c363
+376c368
 <   d2 ∈ [-2147483648..1]
 ---
 >   d2 ∈ [-2468..1]
diff --git a/tests/value/oracle_octagon/CruiseControl.res.oracle b/tests/value/oracle_octagon/CruiseControl.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..7c3d8d711cfb271a197c462226160719fc31b075
--- /dev/null
+++ b/tests/value/oracle_octagon/CruiseControl.res.oracle
@@ -0,0 +1,8 @@
+979c979
+<        [0]._C4_ThrottleCmd._I0_Regul_ON ∈ {0; 1}
+---
+>        [0]._C4_ThrottleCmd._I0_Regul_ON ∈ {1}
+1217c1217
+<        [0]._C4_ThrottleCmd._I0_Regul_ON ∈ {0; 1}
+---
+>        [0]._C4_ThrottleCmd._I0_Regul_ON ∈ {1}
diff --git a/tests/value/oracle_octagon/builtins_split.res.oracle b/tests/value/oracle_octagon/builtins_split.res.oracle
index 4f5a68d6cdb893ccd920cc33c02545f5580bb89d..09146749136af8ba9b8d1975d16dc9d93d042e86 100644
--- a/tests/value/oracle_octagon/builtins_split.res.oracle
+++ b/tests/value/oracle_octagon/builtins_split.res.oracle
@@ -6,7 +6,8 @@
 > [eva] builtins_split.c:104: Call to builtin Frama_C_builtin_split_all
 > [eva] builtins_split.c:104: Call to builtin Frama_C_builtin_split_all
 > [eva] builtins_split.c:104: Call to builtin Frama_C_builtin_split_all
-75a83,89
+75a83,90
+> [eva] builtins_split.c:112: Call to builtin Frama_C_builtin_split_all
 > [eva] builtins_split.c:112: Call to builtin Frama_C_builtin_split_all
 > [eva] builtins_split.c:112: Call to builtin Frama_C_builtin_split_all
 > [eva] builtins_split.c:112: Call to builtin Frama_C_builtin_split_all
diff --git a/tests/value/oracle_octagon/equality.res.oracle b/tests/value/oracle_octagon/equality.res.oracle
index b5553e29dbc35c1e9fb26bff458b2b82b0cc9ca6..24564fbdf1425ff856a02a0ec9fe194fbaa53932 100644
--- a/tests/value/oracle_octagon/equality.res.oracle
+++ b/tests/value/oracle_octagon/equality.res.oracle
@@ -1,3 +1,7 @@
+60c60
+< [eva] equality.c:99: Frama_C_show_each_10_19: [10..42]
+---
+> [eva] equality.c:99: Frama_C_show_each_10_19: [10..19]
 75,76c75,76
 <   y ∈ [0..42] or UNINITIALIZED
 <   w ∈ [0..42] or UNINITIALIZED
diff --git a/tests/value/oracle_octagon/from_termin.res.oracle b/tests/value/oracle_octagon/from_termin.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..d03d84f92d569928f2f9156ff651c33acd1a291b
--- /dev/null
+++ b/tests/value/oracle_octagon/from_termin.res.oracle
@@ -0,0 +1,2 @@
+9a10
+> [eva] from_termin.i:8: starting to merge loop iterations
diff --git a/tests/value/oracle_octagon/gauges.res.oracle b/tests/value/oracle_octagon/gauges.res.oracle
index 3bd3c265780ea7b9be6d67f03047adcaca64da7a..a5e47e28258fe4726d31ff83cb80079321750697 100644
--- a/tests/value/oracle_octagon/gauges.res.oracle
+++ b/tests/value/oracle_octagon/gauges.res.oracle
@@ -1,24 +1,17 @@
-196,197d195
-< [eva:alarm] gauges.c:156: Warning: 
-<   signed overflow. assert -2147483648 ≤ toCopy - 1;
-259,260d256
+259,260d258
 < [eva:alarm] gauges.c:201: Warning: 
 <   signed overflow. assert -2147483648 ≤ numNonZero - 1;
-282,286d277
+282,286d279
 < [eva] gauges.c:218: Frama_C_show_each:
 < [eva] gauges.c:218: Frama_C_show_each:
 < [eva] gauges.c:218: Frama_C_show_each:
 < [eva:alarm] gauges.c:220: Warning: 
 <   signed overflow. assert -2147483648 ≤ n - 1;
-767c758
+767c760
 <   numNonZero ∈ [-2147483648..8]
 ---
 >   numNonZero ∈ {-1}
-778c769
+778c771
 <   n ∈ [-2147483648..99]
 ---
 >   n ∈ {-1}
-839c830
-<   toCopy ∈ [-2147483648..99]
----
->   toCopy ∈ {-1}
diff --git a/tests/value/oracle_octagon/incompatible_states.res.oracle b/tests/value/oracle_octagon/incompatible_states.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..426fe5da2c9673132a9b84c5b02e570002c8ede6
--- /dev/null
+++ b/tests/value/oracle_octagon/incompatible_states.res.oracle
@@ -0,0 +1,4 @@
+58c58
+<   t[0] ∈ {0; 1}
+---
+>   t[0] ∈ {0}
diff --git a/tests/value/oracle_octagon/interpol.res.oracle b/tests/value/oracle_octagon/interpol.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..02af213df51d3952ffc2a08c91d655aadd2de281
--- /dev/null
+++ b/tests/value/oracle_octagon/interpol.res.oracle
@@ -0,0 +1,9 @@
+18,19c18
+< [eva] interpol.c:16: 
+<   Frama_C_show_each_ok: {0; 1; 2; 3; 4; 5; 6}, {-64; -32; -16; -8; -4; -2; -1}
+---
+> [eva] interpol.c:16: Frama_C_show_each_ok: {0; 1; 2; 3; 4; 5; 6}, [-64..-1]
+24c23
+<   d ∈ {-64; -32; -16; -8; -4; -2; -1} or UNINITIALIZED
+---
+>   d ∈ [-64..-1] or UNINITIALIZED
diff --git a/tests/value/oracle_octagon/multidim-relations.res.oracle b/tests/value/oracle_octagon/multidim-relations.res.oracle
index b0dec1503d0277d7ef88871cf86e10906cac0e2b..174d88b2cb0958bb6578a57ae620aef2e75a1bad 100644
--- a/tests/value/oracle_octagon/multidim-relations.res.oracle
+++ b/tests/value/oracle_octagon/multidim-relations.res.oracle
@@ -12,3 +12,7 @@
 > [kernel] multidim-relations.c:21: 
 25a25
 > [eva] Recording results for init_array
+45d44
+< [eva] Recording results for use_array
+47a47
+> [eva] Recording results for use_array
diff --git a/tests/value/oracle_octagon/offsetmap.0.res.oracle b/tests/value/oracle_octagon/offsetmap.0.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..6bebb89e738e4c6703b3d8b869f9d852e34a9e44
--- /dev/null
+++ b/tests/value/oracle_octagon/offsetmap.0.res.oracle
@@ -0,0 +1,4 @@
+40d39
+< [eva] Recording results for g
+42a42
+> [eva] Recording results for g
diff --git a/tests/value/oracle_octagon/offsetmap.1.res.oracle b/tests/value/oracle_octagon/offsetmap.1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..6bebb89e738e4c6703b3d8b869f9d852e34a9e44
--- /dev/null
+++ b/tests/value/oracle_octagon/offsetmap.1.res.oracle
@@ -0,0 +1,4 @@
+40d39
+< [eva] Recording results for g
+42a42
+> [eva] Recording results for g
diff --git a/tests/value/oracle_octagon/partitioning-annots.0.res.oracle b/tests/value/oracle_octagon/partitioning-annots.0.res.oracle
index cd64a1b908f4fcd56dac921a50c0bec490216e7e..141d3a1f322385d29fea8cd73951c79d349d8440 100644
--- a/tests/value/oracle_octagon/partitioning-annots.0.res.oracle
+++ b/tests/value/oracle_octagon/partitioning-annots.0.res.oracle
@@ -1,4 +1,4 @@
-105,106c105,106
+136,137c136,137
 <   x ∈ [0..44]
 <   y ∈ [0..44]
 ---
diff --git a/tests/value/oracle_octagon/redundant_alarms.res.oracle b/tests/value/oracle_octagon/redundant_alarms.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..913f8ab9f773d1c9ba23e01b0551932c560dbeaa
--- /dev/null
+++ b/tests/value/oracle_octagon/redundant_alarms.res.oracle
@@ -0,0 +1,2 @@
+46a47
+> [eva] redundant_alarms.c:39: starting to merge loop iterations
diff --git a/tests/value/oracle_octagon/relations.res.oracle b/tests/value/oracle_octagon/relations.res.oracle
index 74aca336ba48970545ced8311cee9097bd21f1ef..1aba9b820f8395e34b9d9534ab68f1098fd62045 100644
--- a/tests/value/oracle_octagon/relations.res.oracle
+++ b/tests/value/oracle_octagon/relations.res.oracle
@@ -1,7 +1,68 @@
-80,81c80,82
+34,49d33
+< [eva:alarm] relations.i:41: Warning: 
+<   signed overflow. assert -2147483648 ≤ u[5] - u[0];
+< [eva:alarm] relations.i:41: Warning: 
+<   signed overflow. assert u[5] - u[0] ≤ 2147483647;
+< [eva:alarm] relations.i:46: Warning: 
+<   signed overflow. assert -2147483648 ≤ u[10] - u[11];
+< [eva:alarm] relations.i:46: Warning: 
+<   signed overflow. assert u[10] - u[11] ≤ 2147483647;
+< [eva:alarm] relations.i:48: Warning: 
+<   signed overflow. assert -2147483648 ≤ u[1] - u[0];
+< [eva:alarm] relations.i:48: Warning: 
+<   signed overflow. assert u[1] - u[0] ≤ 2147483647;
+< [eva:alarm] relations.i:52: Warning: 
+<   signed overflow. assert -2147483648 ≤ u[5] - u[1];
+< [eva:alarm] relations.i:52: Warning: 
+<   signed overflow. assert u[5] - u[1] ≤ 2147483647;
+60,61c44
+<   u[0] ∈ [-2147483648..2147483646]
+<    [1] ∈ [--..--]
+---
+>   u[0..1] ∈ [-2147483648..2147483646]
+67,78c50,60
+<   R1 ∈ [--..--]
+<   R2 ∈ [--..--]
+<   R3 ∈ [-2147483648..2147483646]
+<   R4 ∈ [--..--]
+<   R5 ∈ [--..--]
+<   R6 ∈ [--..--]
+<   R7 ∈ {0; 1}
+<   A7 ∈ [--..--]
+<   R8 ∈ {0; 1}
+<   A8 ∈ [--..--]
+<   S1 ∈ {-1; 0; 1}
+<   S2 ∈ {0; 1}
+---
+>   R1 ∈ {0; 3}
+>   R2 ∈ {0; 3}
+>   R3 ∈ {0; 2}
+>   R4 ∈ {0; 2}
+>   R5 ∈ {1}
+>   R6 ∈ {0}
+>   R7 ∈ {1}
+>   A7 ∈ {0}
+>   A8 ∈ {1}
+>   S1 ∈ {0}
+>   S2 ∈ {1}
+80,81c62,64
 <   e ∈ [--..--]
 <   f ∈ [--..--]
 ---
 >   e ∈ {1}
 >   f[bits 0 to 7] ∈ {1; 4}
 >    [bits 8 to 31] ∈ [--..--]
+102c85
+<   R7 FROM g (and SELF)
+---
+>   R7 FROM g
+104d86
+<   R8 FROM g (and SELF)
+107c89
+<   S2 FROM pCs; S_pCs[0]{.L0; .L1} (and SELF)
+---
+>   S2 FROM pCs; S_pCs[0]{.L0; .L1}
+112c94
+<     A7; R8; A8; S1; S2; c; e; f; tmp; tmp_0; S_pCs[0]{.T13; .T; .L8}
+---
+>     A7; A8; S1; S2; c; e; f; tmp; tmp_0; S_pCs[0]{.T13; .T; .L8}
diff --git a/tests/value/oracle_octagon/struct2.res.oracle b/tests/value/oracle_octagon/struct2.res.oracle
index 0422f2e21dd0d1c733352d3cab30a7e36443ca16..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/tests/value/oracle_octagon/struct2.res.oracle
+++ b/tests/value/oracle_octagon/struct2.res.oracle
@@ -1,7 +0,0 @@
-77,80d76
-<   accessing out of bounds index. assert 0 ≤ (int)(i + j);
-< [eva:alarm] struct2.i:185: Warning: 
-<   accessing out of bounds index. assert (int)(i + j) < 2;
-< [eva:alarm] struct2.i:185: Warning: 
-98d93
-< [scope:rm_asserts] removing 2 assertion(s)
diff --git a/tests/value/oracle_octagon/unroll.res.oracle b/tests/value/oracle_octagon/unroll.res.oracle
index c82ddd4f31807c175f11f4e55c96313f87a53446..b0b04dfe12a225825d9f1736faa4efc66d5f5b03 100644
--- a/tests/value/oracle_octagon/unroll.res.oracle
+++ b/tests/value/oracle_octagon/unroll.res.oracle
@@ -1,4 +1,6 @@
-20c20
+14a15
+> [eva] unroll.i:39: starting to merge loop iterations
+20c21
 <   G ∈ [17739..2147483647]
 ---
 >   G ∈ [17854..2147483647]
diff --git a/tests/value/oracle_octagon/unroll_simple.res.oracle b/tests/value/oracle_octagon/unroll_simple.res.oracle
index 8a48c42f84b464b622a56e6b0bdf325a1423af5f..0aead1b2497a8c7979e9bfe3c5945cdb38fb4408 100644
--- a/tests/value/oracle_octagon/unroll_simple.res.oracle
+++ b/tests/value/oracle_octagon/unroll_simple.res.oracle
@@ -1,4 +1,6 @@
-17c17
+11a12
+> [eva] unroll_simple.i:16: starting to merge loop iterations
+17c18
 <   G ∈ [8772..2147483647]
 ---
 >   G ∈ [8896..2147483647]
diff --git a/tests/value/partitioning-annots.c b/tests/value/partitioning-annots.c
index d3ab58aaa5069ea02e5298ffff4abd6874bae81b..393b1fe4bbd3e01a353013158fd7fa781ec5b43c 100644
--- a/tests/value/partitioning-annots.c
+++ b/tests/value/partitioning-annots.c
@@ -162,6 +162,61 @@ void test_loop_split()
   }
 }
 
+/*@
+   assigns \result, *p \from i;
+   behavior error:
+     assumes nondet == 0;
+     assigns \result, *p \from i;
+     ensures \result == -1;
+     ensures \initialized(p) && *p == \old(i);
+   behavior positive:
+     assumes nondet > 0;
+     assigns \result \from i;
+     ensures \result >= 10;
+   behavior negative:
+     assumes nondet < 0;
+     assigns \result \from i;
+     ensures \result <= -10;
+   disjoint behaviors;
+   complete behaviors;
+*/
+int spec(int i, int* p);
+
+int body(int i, int *p) {
+  int i2 = i / 2;
+  int absolute = i2 < 0 ? -i2 : i2;
+  int state = nondet % 2;
+  //@ split state;
+  if (state < 0)
+    return - 10 - absolute;
+  if (state > 0)
+    return 10 + absolute;
+  *p = i;
+  return -1;
+}
+
+/* Tests the application of multiple splits according to the return value of a
+   call, to keep in the caller some state partitioning from the callee.
+   The splits must be defined after the call, so the state partitioning from the
+   callee must be kept until all splits are performed.
+   Tests this whether the function body or a specification is used. */
+void test_splits_post_call (void) {
+  int x, y, error;
+  int i = Frama_C_interval(-1000, 1000);
+  int r = spec(i, &x);
+  //@ split r < -1;
+  //@ split r > -1;
+  if (r == -1)
+    error = x; // There should be no alarm.
+  Frama_C_show_each_spec(r, x); // There should be three states.
+  r = body(i, &y);
+  //@ split r < -1;
+  //@ split r > -1;
+  if (r == -1)
+    error = y; // There should be no alarm.
+  Frama_C_show_each_body(r, y); // There should be three states.
+}
+
 void test_history()
 {
   int i = Frama_C_interval(0,1);
@@ -225,4 +280,5 @@ void main(void)
   test_split();
   test_dynamic_split();
   test_dynamic_split_predicate();
+  test_splits_post_call();
 }
diff --git a/tests/value/statistics.i b/tests/value/statistics.i
new file mode 100644
index 0000000000000000000000000000000000000000..329dbef213c9393b226943744f7d24d1694273d6
--- /dev/null
+++ b/tests/value/statistics.i
@@ -0,0 +1,20 @@
+/* run.config
+   LOG: @PTEST_NAME@.csv
+   STDOPT: +" -eva-statistics-file ./@PTEST_NAME@.csv"
+*/
+
+/* This test only dump statistics in the default configuration
+   to avoid oracle duplication. */
+
+void g(int i) {}
+
+void f(int n) {
+  for (int i = 0 ; i < n ; i++) {
+    g(i);
+  }
+}
+
+int main(int n) {
+  f(n);
+  f(n-1);
+}
diff --git a/tools/hdrck/frama-c-hdrck.opam b/tools/hdrck/frama-c-hdrck.opam
index 95cd527fb24a67755af49e542304e628191bedea..acd43dffc4a7122b1a70a7ed71d9f1d2835a920b 100644
--- a/tools/hdrck/frama-c-hdrck.opam
+++ b/tools/hdrck/frama-c-hdrck.opam
@@ -1,7 +1,7 @@
 opam-version: "2.0"
 name: "frama-c-hdrck"
 synopsis: "Frama-C header check tool"
-version: "26.0+dev"
+version: "27.0+dev"
 description:"""
 Performs all checks related to file headers as required by the Frama-C
 continuous integration.
diff --git a/tools/lint/frama-c-lint.opam b/tools/lint/frama-c-lint.opam
index 1965b30ff49e4c3289e1f4e69eda47bdec0fe2cc..08041265966df4bcb34b87e4a768a7faad40342b 100644
--- a/tools/lint/frama-c-lint.opam
+++ b/tools/lint/frama-c-lint.opam
@@ -1,7 +1,7 @@
 opam-version: "2.0"
 name: "frama-c-lint"
 synopsis: "Frama-C lint tool"
-version: "26.0+dev"
+version: "27.0+dev"
 description:"""
 Performs all checks related to source code formatting as required by the Frama-C
 continuous integration. Namely: OCP-indent for ML files, clang-format for E-ACSL