Next: Introduction, Previous: (dir), Up: (dir)
This is the AdaControl User Guide. It describes how to install and use AdaControl. Please refer to the AdaControl Programmer Manual to learn how to add new kinds of rules to AdaControl.
AdaControl is Copyright © 2005-2019 Eurocontrol/Adalog, except for some specific modules that are © 2006 Belgocontrol/Adalog, © 2006 CSEE/Adalog, © 2006 SAGEM/Adalog, or © 2015 Alstom/Adalog. AdaControl is free software; you can redistribute it and/or modify it under terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This unit is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License distributed with this program; see file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate generics from this program, or if you link units from this program with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Public License.
This document is Copyright © 2005-2019 Eurocontrol/Adalog. This document may be copied, in whole or in part, in any form or by any means, as is or with alterations, provided that (1) alterations are clearly marked as alterations and (2) this copyright notice is included unmodified in any copy.
Next: Installation, Previous: Top, Up: Top
AdaControl is an Ada rules controller. It is used to control that Ada software meets the requirements of a number of parameterizable rules. It is not intended to supplement checks made by the compiler, but rather to search for particular violations of good-practice rules, or to check that some rules are obeyed project-wide. AdaControl can also be handy to make statistics about certain usages of language features, or simply to search for the occurrences of particular constructs; its scope is therefore not limited to enforcing programming rules, although it is of course one of its main goals.
AdaContol can also generate commands for suggested fixes to a number
of violations; its companion program adactl_fix can perform
these fixes automatically, or they can be fixed interactively from
GPS.
AdaControl is a commercial product of Adalog with professional grade support available. Getting support is highly recommended for industrial projects. Adacontrol can also be customized or extended to match your special needs, please refer to Support or contact Adalog at info@adalog.fr.
| • Features | ||
| • Support | ||
| • History | ||
| • References |
Next: Support, Previous: Introduction, Up: Introduction
AdaControl analyzes a set of Ada units, according to parameterizable controls. Controls can be given from the command line, from a file, or interactively. There is a wide range of controls available. Some are quite simple (although very useful):
Other rules are quite sophisticated:
and much, much more... See Rules reference for the complete
reference for all possible controls. The rules directory
contains a set of command files; especially, the file verif.aru
contains some commonly accepted rules. It is a good starting point for
devising your own set of rules.
AdaControl is very simple to use. It takes, as parameters, a list of units to process and a list of commands that define the controls to apply. The complete syntax of the commands is described in chapter Command language reference.
AdaControl produces messages to the standard output, unless redirected. Several levels of messages are defined (i.e. error or found), depending on the kind of the control (i.e. check or search).
Rules can be locally disabled for a part of the source code, and various options can be passed to the program.
Ex:
Given the following package:
package Pack is pragma Pure (Pack); ... end Pack;
The following command:
adactl -l "search pragmas (pure)" pack
produces the following result (displayed to standard output):
pack.ads:2:4: Found: PRAGMAS: use of pragma Pure
AdaControl integrates nicely in environments such as GPS (see Running AdaControl from GPS), AdaGide (see Running AdaControl from AdaGide), or emacs (see Control kinds and report messages). In those environments, you can run AdaControl from menus or by just clicking on a button!
Next: History, Previous: Features, Up: Introduction
Adalog provides commercial support for AdaControl. Support includes the following benefits:
Adalog cannot correct problems whose origin is due to compiler bugs or defects in the implementation of ASIS (contact your compiler provider for support on these problems). However, Adalog will do its best effort to find workarounds for such problems.
In addition, Adalog can provide various services:
For pricing information about support contract and other services, please contact info@adalog.fr.
There is a Wiki for questions about AdaControl at
https://sourceforge.net/p/adacontrol/wiki/Home/. This is the
place to ask for information, make suggestions, or get help from the
community.
For problem reports, please create a ticket into our BT system at
https://sourceforge.net/p/adacontrol/tickets/.
If you enjoy AdaControl, there are several things you can do to help us continue and improve this nice project.
And remember: developing AdaControl is an expensive effort (according to Ohlo’s COCOMO model, it is worth 15 man.year of development). We need support from our users to keep it running!
Next: References, Previous: Support, Up: Introduction
The development of AdaControl was initially funded by Eurocontrol (http://www.eurocontrol.int), which needed a tool to help in verifying the million+ lines of code that does Air Traffic Flow Management over Europe. Because it was felt that such a tool would benefit the community at-large, and that further improvements made by the community would benefit Eurocontrol, it was decided to release AdaControl as free software. Later, Eurocontrol, Belgocontrol, Alstom, Ansaldo (formerly CSEE-Transport), and SAGEM-DS sponsored the development of more rules.
The requirements for AdaControl were written by Philippe Waroquiers (Eurocontrol-Brussels), who also conducted extensive testing of AdaControl over the Eurocontrol software. The software was developped by Arnaud Lecanu and Jean-Pierre Rosen (Adalog). Rules, improvements, etc. were contributed by Pierre-Louis Escouflaire (Adalog), Alain Fontaine (ABF consulting), Richard Toy (Eurocontrol-Maastricht), and Isidro Ilasa Veloso (GMV). AdaGide support and improvement of icons were contributed by Gautier de Montmollin. Emmanuel Masker (Alstom), Yannick Duchene and Pascal Pignard contributed to GPS integration.
See file HISTORY for a description of the various versions of
AdaControl, including enhancements of the current version over the
previous ones. Users of a previous version are warned that the rules
are not 100% upward-compatible: this is necessary to make the rules
more consistent and easier to use. However, the incompatibilities are
straightforward to fix and should affect only a very limited number of
files. See Non upward-compatible changes for details.
Previous: History, Up: Introduction
Next: Program Usage, Previous: Introduction, Up: Top
Like any ASIS application, AdaControl can be run only if the compiler available on the system has exactly the same version as the one used to compile AdaControl itself. The executable distribution of AdaControl will work only with GNAT version Community Edition 2019, as distributed by AdaCore. If you are using any other version, please use the source distribution of AdaControl and compile it as indicated below.
Another reason for using the source distribution of AdaControl is that the user may not be interested in all provided rules. It is very easy to remove some rules from AdaControl to increase its speed. See Customizing AdaControl.
| • Building and installing AdaControl from source | ||
| • Installing an executable distribution | ||
| • Installing support for AdaGide | ||
| • Installing support for GNATdashboard integration |
Next: Installing an executable distribution, Previous: Installation, Up: Installation
This section is only for the source distribution of AdaControl. If you downloaded an executable distribution (and are using the latest version of GNAT Community Edition), you may skip to the next section.
ASIS is continuously evolving to support Ada-2005/2012 features, and so is AdaControl. As a consequence, the full set of features of AdaControl is supported only with recent versions of Gnat, namely with GnatPRO 7.2.0 and GnatGPL-2013 (and higher). We refer to these versions as the “new Gnat”, and we encourage all users to use the latest versions.
Some users may however need to use an older version of Gnat. We provide also a version of AdaControl that is compatible with versions GnatPRO 7.0.x and GnatGPL-2011 and older (before some incompatible -but necessary- changes in ASIS happened). We refer to these versions as the “old Gnat”.
The old gnat version is now frozen; it does not provide controls related to Ada-2012 (or that depend on new features of ASIS) and will not receive any new features or improvements in the future, unless requested by a supported customer (such requests will be honoured as part of the support contract). See Support for information on becoming a supported user. This version can be obtained (in source only) from the Git repository of AdaControl on SourceForge (http://adacontrol.sourceforge.net), branch “master-old_gnat”.
Intermediate releases of Gnat (GnatPRO-7.1.x, GnatGPL-2012) are not fully compatible with either of these distributions. Depending on exact version, problems may range from compilation errors to incorrect results in some rare (Ada 2012) cases. Compatible sources can be obtained from the Git repository of AdaControl on SourceForge (http://adacontrol.sourceforge.net), branch “GPL2012”. We will be happy to help our supported customers who must use one of these versions.
The following software must be installed in order to compile AdaControl from source:
Make sure to have the same version of GNAT and ASIS. The version used for running AdaControl must be the same as the one used to compile AdaControl itself.
As mentionned above, support of Gnat .gpr projects requires the
GNATColl component from AdaCore. If for some reason you don’t want to
include this component, it is possible to build AdaControl without
this support. To do so, go to the src directory and modify the
file implementation_options-project_file.ads as indicated. If
you don’t have GNATColl installed at all, you need also to remove the
line that says “with gnatcoll;” from the file
build.gpr.
Run the installer (adactl_src-setup.exe). This will
automatically build and install AdaControl, no other installation is
necessary.
Simply go to the root directory of the distribution and type:
gprbuild build.gpr gprinstall -p build.gpr
You’re done!
NOTE: the “-p” option of gprinstall creates possibly missing directories. If you are installing over a previous version of AdaControl, you may want to add the “-f” option to allow the replacement of existing files.
If you want to uninstall AdaControl, just use:
gprinstall --uninstall adacontrol
Caveat (old gnat only): Due to a bug in some versions, if you are using GNATPro 6.1.2 and above, you must set the variable GNAT_FIX to 1; i.e. invoke the command as:
gprbuild -Pbuild.gpr -XGNAT_FIX=1
or if gprbuild is not available for your distribution:
gnatmake -Pbuild.gpr -XGNAT_FIX=1
It is also possible to build and install AdaControl with a regular Makefile, although it does little more than run the previous commands. This is mainly useful if you want to embed AdaControl into some distribution that uses Makefiles, or if you want to change the default compilation options (see comments in Makefile for details).
Go to the root directory of the distribution and type:
make build make install
It is also possible to delete object files and do other actions with this “Makefile”, run the following command to get more information:
make help
NOTE: Building AdaControl needs the “make” command provide with GNAT; it works both with WIN32 shell and UNIX shell.
Automatic install will place AdaControl’s files in standard locations, in your Gnat installation tree. You can skip this section unless you want different locations (for example, if GPS is not installed in the Gnat tree).
All you need to run AdaControl is the executable named adactl
under Linux and MacOS or adactl.exe under Windows. In addition,
the adactl_fix (or adactl_fix.exe under Windows) utility
is necessary if you want to use the automatic fixing
capability. See Automatic fixing. Similarly, pfni (or pfni.exe
under Windows) is a convenient utility, required by the GPS
support. See pfni. Copy these executables (found in the root
directory of the distribution) to any convenient directory on your
path.
To also add AdaControl support to GPS, copy the file
GPS/adacontrol.xml into the <GNAT_dir>/share/gprconfig
directory; copy all other files from the GPS directory into the
<GPS_dir>/share/gps/plug-ins directory. Copy also HTML files
from the doc directory into the
<GPS_dir>/share/doc/gps/html to access AdaControl’s guides from
the "Help" menu of GPS.
It should be possible to compile AdaControl with other compilers than
GNAT, although we didn’t have an opportunity to try it. If you have
another compiler that supports ASIS, note that it may require some
easy changes in the package Implementation_Options to give
proper parameters to the Associate procedure of ASIS. Rules
that need string pattern matchings need the package
Gnat.Regpat. If you compile AdaControl with another compiler,
you can either port Gnat.Regpat to your system, or use a
(limited) portable implementation of a simple pattern matching
(package String_Matching_Portable). Edit the file
string_matching.ads and change it as indicated in the comments.
No other change should be necessary.
Alternatively, if you are using another compiler, you can try and compile your program with GNAT just to be able to run AdaControl. However, compilers often differ in their support of representation clauses, which can cause your program to be rejected by GNAT. In that case, we provide a sed script to comment-out all representation clauses; this can be sufficient to allow you to use AdaControl. See unrepr.sed.
Testing AdaControl needs a UNIX shell, so it works only with UNIX systems. However, it is possible to run the tests on a WIN32 system by using an UNIX-like shell for WIN32, such as those provided by CYGWIN or MSYS. To run the tests, enter the following commands:
cd test ./run.sh
All tests must report PASSED. If they don’t, it may be due to one of the following issues:
tfw_help reports “FAILED” because
it includes a check on the version of AdaControl, and the version
string refers to a different version of Gnat. The only difference (you
can see it by typing “d” when prompted for checking the differences)
should be the name of the compiler.
If there are some rules that you are not interested in, it is very easy to remove them from AdaControl:
src directory, edit the file
framework-plugs.adb. There is a with clause for each
rule (children of package Rules). Comment out the ones you
don’t want.
framework-plugs.adb. There will be error messages
about unknown procedure calls. Comment out the corresponding lines.
It is also possible to add new rules to AdaControl. If your favorite rules are not currently supported, you have several options:
Next: Installing support for AdaGide, Previous: Building and installing AdaControl from source, Up: Installation
If you downloaded the Windows installer executable version of
AdaControl, simply run adactl_exe-setup.exe. This will install
all the files in the recommended locations (as has been done with the
Windows installer source version), including GPS support if you have
GPS installed and/or AdaGide support if you have AdaGide installed.
Otherwise, go to the root directory of the installation and type:
gprinstall -p inst.gpr
This will install the executables and the GPS support in the standard locations (the Gnat directory). Add the “-f” option to gprinstall if you are installing over a previous installation of AdaControl. However, if you are using AdaGide, the support will have to be installed manually as explained below.
If you want to uninstall AdaControl, just use:
gprinstall --uninstall adacontrol
Next: Installing support for GNATdashboard integration, Previous: Installing an executable distribution, Up: Installation
To add AdaControl support to AdaGide, copy the file
AdaControl.tdf from the AdaGide directory of the
distribution into AdaGide’s root directory. Note that AdaControl
support requires AdaGide version 7.42 or above.
Previous: Installing support for AdaGide, Up: Installation
Integration into GNATdashboard is provided in a separate package that
you can download from the same source that you obtained AdaControl
from. It is provided as a .zip file that contains two files:
adacontrol-plugin-1.1r.jar and adacontrol.py.
Of course, the prerequisite is that you have a working installation of
GNATdashboard, including SonarQube and its sonnar-scanner
utility. Copy the first (.jar) file into the
<sonarqube-dir>/extensions/plugins/ directory. Copy the second
(.py) file into the <gnat-dir>/share/gnathub/extras/
directory.
Next: Command language reference, Previous: Installation, Up: Top
AdaControl is a command-line program, i.e. it is normally called directly from the system shell. Options are introduced by a “-” followed by a letter and can be grouped as usual. Some options take the following word on the command line as a value; such options must appear last in a group of options. Parameters are words on the command line that stand by themselves. Options and parameters can be given in any order.
The syntax for invoking AdaControl in regular mode is:
adactl [-deEirsTuvwx]
[-p <project file>] [-f [<command file>]] [-l <commands>]
[-F <format>] [-o [<output file>]] [-t <trace file>]
[-G [<fix level>]] [-S <statistics level>]
[-m <warning limit>] [-M <message limit>]
{<unit>[+|-<unit>]|[@]<file>} [-- <ASIS options>]
AdaControl can process all versions of Ada, up to Ada-2012. If you are using Ada-2005 (or Ada-2012) features, make sure that GNAT is set up for Ada-2005/2012 (this is the default for GNAT Community Edition). Due to technical reasons, the -gnat05 or -gnat12 option cannot be passed to the compiler in “compile on the fly” mode, but you can do any of the following:
pragma Ada_05; (or pragma Ada_12;)
pragma Ada_05 (or pragma Ada_12;) on top
of every compilation unit that uses Ada-2005/2012 features;
Note that if your program is pure Ada-95 and you are using a version
of GNAT where Ada-2005 or above is the default (especially GNAT
Community Edition), and in the rare cases where your program would not
compile in Ada-2005 mode (notably if you have a function that returns
a task type), you can force Ada-95 the same way by using
pragma Ada_95 instead.
Next: Return codes, Previous: Program Usage, Up: Program Usage
| • Input units | ||
| • Commands | ||
| • Output file | ||
| • Output format | ||
| • Output limits | ||
| • Project files | ||
| • Local disabling control | ||
| • Verbose and debug mode | ||
| • Treatment of warnings | ||
| • Exit on error | ||
| • ASIS options |
Next: Commands, Previous: Command line parameters and options, Up: Command line parameters and options
Units to be processed are given as parameters on the command
line. Note that they are Ada compilation unit names, not
file names: case is not significant, and there should be no
extension! Child units are allowed following normal Ada naming rules:
Parent.Child, but be aware that specifying a child unit will
automatically include its parent unit in the analysis. Subunits are
processed during the analysis of the including unit; there is
therefore no need to specify subunits explicitely. If you do specify a
subunit explicitly, it will result in the whole enclosing unit being
analyzed.
However, as a convenience to the user, units can be specified as file names, provided they follow the default GNAT naming convention. More precisely, if a parameter ends in “.ads” or “.adb”, the unit name is extracted from it (and all “-” in the name are substituted with “.”). File names can include a path; in this case, the path is automatically added to the list of directories searched (“-I” ASIS option). The file notation is convenient to process all units in a directory, as in the following example:
adactl -f my_rules.aru *.adb
In the unlikely case where you have a child unit called Ads or
Adb, use the “-u” option to force interpretation of all
parameters as unit names.
By default, both the specification and body of the unit are processed; however, it is possible to specify processing of the specification only by providing the “-s” option. If only file names are given, the “-s” option is assumed if all files are specifications (“.ads” files). It is not possible to specify processing of bodies only, since rules dealing with visibility would not work.
The “-r” option tells AdaControl to process (recursively) all user units that the specified units depend on (including parent units if the unit is a child unit or a subunit). Predefined Ada units and units belonging to the compiler’s run-time library are never processed.
Ex:
adactl -r -f my_rules.aru my_main
will process my_main and all units that my_main depends
on. If my_main is the main procedure, this means that the whole
program will be processed.
If both options “-r” and “-s” are given, then AdaControl will process all units given on the command line, plus (recursively) the specifications (but not the bodies) of all units that the given units depend on. In short, it will process the minimal transitive closure of all compilation units that are necessary to compile the units given on the command line.
It is possible to specify more than one unit (not file) to process in a parameter by separating the names with “+”. Conversely, it is possible to specify units that are not to be processed, separated by “-”. When a unit is subtracted from the unit list, it is never processed even if it is included via the recursive option, and all its child and separate units are also excluded. This is convenient to avoid processing reusable components, that are not part of a project. For example, if you want to run AdaControl on itself, you should use the following command:
adactl -f my_rules_file.aru -r adactl-asis-a4g-gnatcoll
This applies the rules from the file my_rules_files.aru to
AdaControl itself, but not to units that are part of ASIS (units
Asis, A4G, and their children) that would be found by
the “-r” (recursive) option otherwise.
Alternatively, it is possible to provide units indirectly with a parameter consisting of an “@” followed by the name of a file. This file must contain a list of unit names (not files), one on each line. Only the first “word” of the line is considered, i.e. everything after the first blank is ignored. This can be useful to annotate unit names. All units whose names are given in the file will be processed. In addition, some lines have a special meaning:
Ex:
adactl -f my_rules.aru @unit_file.txt
If no input units are specified on the command line, but a project file is given which specifies a units file, the units from the units file are processed. If the project file has no units file, but one or several main files are given, the main files are processed (in recursive mode if the recursive option is also given in the project file). See Project files.
Next: Output file, Previous: Input units, Up: Command line parameters and options
Commands specify which processing AdaControl should apply to units. See Command language reference for a detailed description of all commands.
Commands can be given directly on the command line with the “-l” option. A commands list must be quoted with “"”.
Ex:
adactl pack.ads proc.adb -l "check instantiations (My_Generic);"
It is possible to pass several commands separated by “;”, but as a convenience to the user, the last “;” may be omitted.
Commands can also be read from a file, whose name is given after the
“-f” option (the “.aru” extension is taken by default). As
a special case, if the file name is “-”, commands are read from the
standard input. This is intended to allow AdaControl to be pipelined
behind something that generates commands; if you want to type commands
directly to AdaControl, the interactive mode is more
appropriate. See Interactive mode.
Alternatively, AdaControl will consider a command file set as default in a .gpr project file, unless an explicit “-f” option is given.
Ex:
adactl -f my_rules.aru proc.adb
Note that the “-l” and “-f” options are not exclusive: if both are specified, the commands to be performed include those in the file (first) and then those given on the command line.
This applies also when there is no “-f” option, but a .gpr file is given which includes a default command file. If you need a project file, and don’t want its default command file to be considered, use “-f” without a <command file>.
Next: Output format, Previous: Commands, Up: Command line parameters and options
Messages produced by controls are output to the output file; by default, it is the standard output, but it can be changed by specifying the “-o” option. The output can be forced to the standard output by giving the “-o” option without a file name; this can be useful to override a “-o” option given in a project file. See Project files.
Ex:
adactl -f my_rules.aru -o my_output.txt proc.adb
If the output file exists, new messages are appended to it. This allows running AdaControl under several directories that make up the project, and gathering the results in a single file. However, if the “-w” option is given, AdaControl overwrites the output file if it exists.
All other messages, including syntax error messages, units processed (in verbose mode), and possible internal error mesages from AdaControl itself are output to the standard error file.
Next: Output limits, Previous: Output file, Up: Command line parameters and options
The “-F” option selects the output format. It must be followed by “Gnat”, “Gnat_Short”, “CSV”, “CSV_Short”, “Source”, “Source_Short”, or “None” (case insensitive). By default, the output is in “Gnat” format, unless an output file is specified with a name whose extension is “.csv” (in any casing), in which case it defaults to “CSV”.
The “-S” option selects which statistics are output after each run. It must be followed by a value in the range 0..3. See Control kinds and report messages for details on the various statistics levels.
The “-T” option prints a summary of timing at the end of each run. This indicates how long (in real-time seconds) was spent in processing each rule.
The “-G” option controls the generation, in the output file, of commands for fixing violations. It must be followed by “none” (the default), where no fixes information is generated, “check”, where fixes information is generated only for messages that use “check”, or “search” where fixes information is generated for all messages (i.e. “search” messages and above). Fixes information is never generated for “count”.
Ex:
adactl -F CSV -S 2 -f my_rules.aru -o my_output.csv proc.adb
Next: Project files, Previous: Output format, Up: Command line parameters and options
The “-m” and “-M” options are used to limit the output of AdaControl. These options are followed by an integer value that specifies the maximum number of error messages (“-m”) or warning and error messages (“-M”). If the value is omitted, a previous limitation (comming for example from a command file) is cancelled.
If the indicated number of messages is exceeded during a run, AdaControl stops immediately.
Next: Local disabling control, Previous: Output limits, Up: Command line parameters and options
Starting with version 1.18, AdaControl supports GNAT project files
(“.gpr”). The “-p” option is used to provide the name of a project
file. If this name is a relative name, it is searched for in the
current directory, then on the paths from the file whose name is given
by the environment variable GPR_PROJECT_PATH_FILE and then on
paths indicated by the environment variables GPR_PROJECT_PATH
and ADA_PROJECT_PATH. This is the same algorithm as used by the
various GNAT tools.
Ada units to analyze will be searched in all “source_dirs” specified in the project file or one of the projects it depends on (directly or indirectly). In addition, if the project file specifies a command file for AdaControl, this file will be considered, unless there is also an explicit “-f” option.
Similarly, if no units are given on the command line, AdaControl processes the units from the units file of the project file if any, or the main files from the project file.
More generally, any option not given on the command line is taken from the project file. Especially, units are processed recursively if the project file specifies the recursive option, the output is verbose if the project file specifies the verbose option, etc.
In short, if you specify AdaControl parameters in the project file, you only need to pass the “-p” option to it.
Ex:
adactl -f my_rules.aru -p proj.gpr proc.adb
Alternatively, an old emacs project file (the file with a “.adp” extension used by the Ada mode of Emacs and older versions of AdaControl) can also be specified with the “ -p” option. AdaControl will consider all the directories mentioned in “src_dir” lines from the project file.
If you have specified an output file in the project file, it will be used by default (like for any other option) if you run AdaControl from the command line; therefore, all messages will go to the output file. If you want to force output to the console, use the “-o” option without a file name.
Next: Verbose and debug mode, Previous: Project files, Up: Command line parameters and options
The “-i” option tells AdaControl to ignore disabling markers in Ada
source code (see Disabling controls); i.e. all controls will be
performed, regardless of the presence of disabling markers. This is
equivalent to the command “set ignore ON;”. Note that if you
have many messages, setting this option can speed-up AdaControl
considerably. It is therefore advisable to always set this option
when you know that there is no disabling marker in your source code.
The “-j” option tells AdaControl to invert the meaning of disabling
markers, i.e. only messages marked as disabled will be printed. This
is useful to check which messages have been disabled. This is
equivalent to the command “set ignore INVERTED;”.
Next: Treatment of warnings, Previous: Local disabling control, Up: Command line parameters and options
In the default mode, AdaControl displays only messages from triggered controls. It is possible to get more information with the verbose option (“-v”). In this mode, AdaControl displays a a progress indicator and unit names as they are processed, and its global execution time when it finishes. Note that the progress indicator includes an indication of the run number if there are more than one “go” command.
The “-d” option enables debug mode. This mode provides more information in case of an internal program error, and is of little interest for the casual user, unless you want to report a problem. See In case of trouble.
In debug mode, AdaControl may also, in rare occasions (and only with some versions of GNAT), display ASIS “bug boxes”; this does not mean that something went wrong with the program, but simply that an ASIS failure was properly recovered by AdaControl.
Output of the messages printed by the “-d” option can be directed to a “trace” file (instead of being printed to the standard error file). This is done by the “-t” option, which must be followed by the file name. If the trace file exists, new messages are appended to it.
Next: Exit on error, Previous: Verbose and debug mode, Up: Command line parameters and options
The “-e” option tells AdaControl to treat warnings as errors, i.e. to report a return code of 1 even if only “search” controls were triggered. See Return codes. It does not change the messages however.
Conversely, the “-E” option tells AdaControl to not report warnings at all, i.e. only errors are reported. However, if you ask for statistics, the number of warning messages is still counted. See Control kinds and report messages.
Next: ASIS options, Previous: Treatment of warnings, Up: Command line parameters and options
If an internal error is encountered during the processing of a unit, AdaControl will do its best effort to recover and to continue to process other units. However, if the “-x” option is given, AdaControl will stop on the first error encountered. This option is mainly useful if you want to debug AdaControl itself (or your own rules). See In case of trouble.
Ex:
adactl -x -f my_rules.aru proc.adb
Previous: Exit on error, Up: Command line parameters and options
Everything that appears on the command line after “--” will be treated as an ASIS option, as described in the ASIS user manual.
Casual users don’t need to care about ASIS options, except in one case: if you are running AdaControl from the command line (not from GPS), and if the units that you are processing reference other units whose source is not in the same directory, AdaControl needs to know how to access these units (as GNAT would). This can be done either by using a project file with the “-p” option (see Project files), by putting the appropriate directories into the ADA_INCLUDE_PATH environment variable, or by passing “-I” options to ASIS.
It is possible to pass one or several “-I” options to ASIS, to provide other directories where sources can be found. The syntax is the same as the “-I” option for GNAT.
Other ASIS options, like the “-Cx” and/or “-Fx” options, can be specified. Most users can ignore this feature; however, specifying these options can improve the processing time of big projects. See Optimizing Adacontrol.
Next: Environment variable and default settings, Previous: Command line parameters and options, Up: Program Usage
In order to ease the automation of controlling programs with shell scripts, AdaControl returns various error codes depending on how successful it was. Values returned are:
Next: Fixing violations, Previous: Return codes, Up: Program Usage
If the environment variable “ADACTLINI” is set, its content is taken as a set of commands (separated by semi-colons) that are executed before any other command. Although any command can be specified, this is intended to allow changing default settings with “set” commands. See Set command.
For example, you can set ADACTLINI to “set format Gnat_Short” if you prefer having you messages in short format rather than the (default) long format.
Next: Interactive mode, Previous: Environment variable and default settings, Up: Program Usage
If the “-G” option is given with “check” or “search”, AdaControl generates in the output file (in addition to the regular messages) special directives to fix the source that violated some rule. See Output format.
Not all rule provide automatic fixing, either because the rule is just intended to report on the presence of some construct, or because the fix needs manual inspection. When a rule does provide for automatic fixing, there is a “Fixes” section in its description that explains what can (or cannot) be fixed by the rule.
If the output file is loaded into GPS (automatically, or as a result file), messages for which there is a known fix will appear as usual, but with the “Fix” symbol (the little wrench icon) in the left margin. Clicking on the icon will perform the fix and remove the corresponding icon (just like fixable compilation errors).
Alternatively, there is an “Apply all fixes” entry in the AdaControl menu. This will apply all fixes, just as if you clicked on every “Fix” symbol. Note that the “Undo” command can be used to revert the effect of this command!
Note that by default, the generation of fixes is enabled under GPS.
An output file containing the directives can be processed by the
adactl_fix utility. The syntax is:
adactl_fix [-v] [-o <output-prefix>] <file>... adactl_fix -h
With the “-h” option, adactl_fix prints a brief help message
and exits, ignoring all other options and parameters.
Otherwise, adactl_fix reads the indicated <file>s (more than
one can be provided) and performs the corresponding fixes. The
modified files are printed on the standard output, which can be
redirected to a file for later splitting at an appropriate place with
gnatchop. Alternatively, if the “-o” option is given, each
modified file is output to a file whose name is obtained by prefixing
the <output-prefix> of the "-o" option to the original name of the
corresponding source file. The <output-prefix> can be any string, and
is not analyzed by Adactl_Fix. A prefix like "result/" will result in
all the output going to the directory "result", with the same name as
the original. Alternatively, a prefix like "new-" will result in all
output files being in the same directory, with a "new-" prepended to
the name. Adactl_Fix will overwrite any existing file with the same
name.
The “-v” (verbose) option prints the names of the fix files being processed and of the source files being fixed to the standard error file. In case of conflicts, it provides some more information about the origin of the conflict.
It is possible that several fixes modify the same place, or overlapping places. When using automatic fixing, if one of the fixes is the deletion of a zone of text that fully covers the other one, then the deletion is kept and the other one discarded. Otherwise, the first fix is kept and the other one is ignored; a message at the end of the run tells the user that some fixes were not performed, and that AdaControl should be run again.
When this happens, it is possible (although we expect it to be infrequent) that the modified code does not compile anymore and that some easy manual adjustments be necessary.
It is expected that this algorithm for resolving conflicts be improved in the future. Suggestions and examples welcome!
When using interactive fixing, all fixes are kept; just click on the various “fix” icons, and check that the code is transformed appropriately.
Automatic fixing is a powerful feature of AdaControl, but like any tool that transforms the source it requires some care. Automatic fixing makes sense when there are many violations, and these violations would be easy but tedious to fix by hand. A typical use case is when you apply new rules to an existing software, and discover that the casing rules have not been obeyed: fixing the casing of thousands of identifiers is a long and uninteresting job... Therefore, the automatic fixing tool has been designed under the assumption that it will be used “one-shot”, not as day-to-day use.
The automatic fixing should therefore be used as follows:
On the other hand, interactive fixing is fully under user control. It is possible to check (and possibly undo) any modification. But of course, since it is a manual operation, it becomes tedious when there are many changes to perform.
As a rule of thumb, perform automatic fixing, one rule at a time, for the controls that often result in a big number of violations, and where the fix is both obvious and riskless (typically: incorrect casing of identifiers or keywords). Use interactive fixing for more subtile controls where it is more appropriate to check the result of the substitution.
Caveat: fixing a violation can create another violation! Typically, if the fix adds some text (like changing a positional association to a named one), it can then exceed the maximum allowed line length. Hence fixing violations is necessarily an iterative process.
And of course, the best advice is: fix violations as early as possible. Run AdaControl each time you modify a module. This is the best way to save the effort!
If you have specified a fix level in the project file, it will be used by default (like for any other option) if you run AdaControl from the command line; therefore, fixes will be generated, which might be undesirable for console output. To disable the generation of fixes, use the “-G” option without value (same as “-G none”).
Attention of users designing safety critical applications (DOD-178B/C level A, EN-50128 SIL4) is drawn to the fact that the automatic fixing is relevant to TQL1-4, instead of TQL5 as AdaControl normally is.
AdaControl has not been subject to the formal verifications required by TQL1-4 tools; therefore it is up to the user to check that the applied fixes maintain the integrity of the software.
Next: Other execution modes, Previous: Fixing violations, Up: Program Usage
The “-I” option tells AdaControl to operate interactively. In this mode, commands specified with “-l” or “-f” options are first processed, then AdaControl prompts for commands on the terminal. Note that the “quit” command (see Quit command) is used to terminate AdaControl.
The syntax of commands run interactively is exactly the same as the one used for files; especially, each command must be terminated with a “;”. Note that the prompt (“Command:”) becomes “.......:” when AdaControl requires more input because a command is not completely given, and especially if you forget the final “;”.
As with files, it is possible to give several commands on a single line in interactive mode. If a command contains syntax errors, all “go” commands (see Go command) on the same line are temporarily disabled. Other commands that do not have errors are normally processed however.
The interactive mode is useful when you want to do some analysis of your code, but don’t know beforehand what you want to control. Since the ASIS context is open only once when the program is loaded, queries will be much faster than running AdaControl entirely with a new query given in a “-l” option each time. It is also useful to experiment with AdaControl, and to check interactively commands before putting them into a file.
Next: Running AdaControl from GPS, Previous: Interactive mode, Up: Program Usage
In addition to normal usage, AdaControl features special options to ease its use; no Ada unit is analyzed when using these options.
| • Getting help | ||
| • Checking commands syntax | ||
| • Generating a units list |
Next: Checking commands syntax, Previous: Other execution modes, Up: Other execution modes
The “-h” option provides help about Adacontrol usage. If the “-h” option is given, no other option is analyzed and no further processing happens.
Syntax:
adactl -h [<keyword> | <rule name> | variables ["<pattern>"] ...]
<keyword> ::= all | commands | license | list |
options | rules | version
The “-h” option without parameter displays a help message about usage of the AdaControl program, the various options, and the rule names.
Otherwise, the “-h” must be followed by one or several keywords or rule names (case irrelevant); its effect is:
Ex:
adactl -h pragmas Unnecessary_Use_Clause adactl -h all adactl -h version license adactl -h stat
Note in the last example that “stat” is not the name of a rule; it is therefore interpreted as a pattern, and help will be displayed for all rules that include the string “stat” in their name. This can be very convenient to retrieve the name of a rule if you don’t remember exactly how it is spelled.
Next: Generating a units list, Previous: Getting help, Up: Other execution modes
The “-C” option is used to check syntax of commands without executing any control.
Syntax:
adactl -C [-dv] [-f <command file>] [-l <rules list>]
In this mode, AdaControl simply checks the syntax of the commands provided with the “-l” option, or of the commands provided in the file named by the “-f” option (at least one of these options must be provided). No other processing will happen.
AdaControl will exit with a return code of 0 if the syntax is correct, and 2 if any errors are found. A confirming message that no errors were found is output if the “-v” option is given.
This option is especially useful when you have modified a command file, before trying it on many units. The way AdaControl works, it must open the ASIS context (a lengthy operation) before analyzing the rules. This option can therefore save a lot of time if the command file contains errors.
Previous: Checking commands syntax, Up: Other execution modes
The “-D” options produces a list of units that can be reused as an indirect file in later runs.
Syntax:
adactl -D [-rsvw] [-o <output file>] [-p <project file>]
{<unit>[+|-<unit>]|[@]<file>} [-- <ASIS options>]
In this mode, AdaControl outputs the list of units that would be processed. It is especially useful when used with the “-r” option and given the main unit name, since it will then generate the whole dependencies list (hence the name “D”), i.e. the list of units that are part of the program. However, if -D is used with -s, the list includes only transitive dependencies from the specifications of required units (but not from their bodies). This is the list of all units required to compile the given units.
The list can be directed to a file with the “-o” option (if the file exists, it won’t be overwritten unless the “-w” option is specified). This file can then be used in an indirect list of units. See Input units. Note that it is more efficient to create the list of units once and then use the indirect file than to specify all applicable units or use the “-r” option each time AdaControl is run.
If you use the “-Drs” option to generate the minimum set of required units to compile the given unit, note that some units may still be missing when the compiler requires the presence of a body due to inlining of subprograms or generic instantiations. These units depend on the compiler and cannot be computed from the text of the program alone.
Next: Running AdaControl from AdaGide, Previous: Other execution modes, Up: Program Usage
AdaControl integrates nicely into GPS, making it even easier to use. It can be launched from menu commands, and parameters can be set like any other GPS project parameters. When run from within GPS, AdaControl will automatically retrieve all needed directories from the current GPS project.
After running AdaControl, the “locations” panel will open, and you can retrieve the locations of errors from there, just like with a regular compilation. Errors will be marked in red in the source, warning will be marked orange, and you will have corresponding marks showing the places of errors and warnings in the speedbar. Note that AdaControl errors appear under the “AdaControl” category, but if there were compilation errors, they will appear under the “Compilation” category. Final counts from “count” control kinds will appear under the “Counts summary” category, and statistics under the “Statistics” category.
| • The AdaControl menu and buttons | ||
| • Contextual menu | ||
| • AdaControl switches | ||
| • AdaControl preferences | ||
| • AdaControl language | ||
| • AdaControl help | ||
| • Caveat |
Next: Contextual menu, Previous: Running AdaControl from GPS, Up: Running AdaControl from GPS
AdaControl adds an “AdaControl” menu to GPS, with several submenus:
There are also two buttons representing Lady Ada in a magnifier glass in the toolbar, one with a red question mark in the background. These buttons launch AdaControl, by default on the file currently being edited; however, you can change this behaviour from the preferences to control either files from a list, or all files from the project. The button without the question mark uses rules from the current rules file, while the one with the question mark asks for the control to apply interactively.
Here are some tips about using the “interactive” menus (or the button with the question mark):
Next: AdaControl switches, Previous: The AdaControl menu and buttons, Up: Running AdaControl from GPS
AdaControl adds two entries to the contextual menus (right click) of
Ada files. They call the pfni utility on the current
entity. See pfni. The entry “Print full name” displays the full
name of the entity in simple form, while the entry “Print full name
(with overloading)” ) prints it with overloading information. If the
name refers to an entity which is initialized (or to a parameter with
a default value), the initial value is printed. If the entity is a
discrete type, its range is printed. If the entity is an array type,
the ranges of its indices are printed.
This is convenient to find how to name entities in rule files. See Specifying an Ada entity name. It is also convenient to find where an entity is declared, and which of several overloaded entities is being referred to.
This is also convenient to find the actual value of a constant from anywhere in the program text, since the printed value is completely evaluated if it is a (static) expression.
Next: AdaControl preferences, Previous: Contextual menu, Up: Running AdaControl from GPS
The tab “switches” from the “Project/Edit Project Properties” menu includes a page for AdaControl, which allows you to set various parameters. Since the GPS interface analyzes the output of AdaControl, you should not set options directly in the bottom window of this page (the one that displays the actual options passed to AdaControl).
This section controls the definition of various files used by AdaControl.
This section offers options that control how units are processed.
This section controls the debugging options of AdaControl.
This section offers options that control where and how the output of AdaControl is displayed.
This section controls the ASIS parameters passed to AdaControl. The content of the input field “ASIS options” is used in place of the standard (“-CA -FM”) one.
Casual users don’t need to change the default ASIS options. For more details, see ASIS options.
Next: AdaControl language, Previous: AdaControl switches, Up: Running AdaControl from GPS
There is an entry for AdaControl in the “edit/preferences” menu:
Next: AdaControl help, Previous: AdaControl preferences, Up: Running AdaControl from GPS
If you check “AdaControl” in the “Languages” tab of the project
properties, GPS will recognize files with extension .aru as
AdaControl command files, and provide appropriate colorization. Remember
to check also the corresponding “no compiler” checkbox to avoid
spurious messages from GPS.
Next: Caveat, Previous: AdaControl language, Up: Running AdaControl from GPS
The AdaControl User Manual (this manual) and the AdaControl Programmer Manual are available from the "Help/AdaControl" menu of GPS.
The "Help on rule" entry displays the list of all rules; if you click on one of them, you get help for the particular rule. Depending on the setting of the “Help on rule” preference (see above), it opens a pop-up that displays the rule(s) purpose and the syntax of its parameters, or opens the user guide at the appropriate location.
The “About” entry displays a popup with AdaControl’s version number and license condition.
Previous: AdaControl help, Up: Running AdaControl from GPS
GPS may crash when the output of a command is too big (i.e. hundreds of messages with AdaControl). If this happens, use the “preferences” menu to limit the number of messages.
Next: Integrating AdaControl into GNATdashboard, Previous: Running AdaControl from GPS, Up: Program Usage
If you want to use AdaControl from AdaGide, make sure you have copied
the necessary file into the required place. See Installing support for AdaGide. Note that AdaGide does not have all the parameterization
facilities of sophisticated environments like GPS, but all AdaControl
options, like the name of the command file or the output format, can
easily be changed by editing the tool description file
AdaControl.tdf.
AdaGide now features several AdaControl commands from the “tool” menu:
verif.aru.
Next: Helpful utilities, Previous: Running AdaControl from AdaGide, Up: Program Usage
Once GNATdashboard support is installed, AdaControl is usable like any
other tool that comes with GNATdashboard. The name of the plug-in is
“adacontrol”. It can be given either on the command line of
gnathub or in the “Plugins” attribute of the “Dashboard”
package of a project file.
Extra options for AdaControl can be given using the
--targs:adacontrol option of GNAThub. However, the simplest way
to give fundamental options is to give a units file and the command
file in the project file: in the absence of explicit parameters on the
command line, these will be taken by default.
AdaControl installs a non-default profile called “AdaControl way” that contains all AdaControl rules. Use it to activate the rules you need. You can also make it inherit from “GNATdashboard way” if you want to use AdaControl with other GNAT tools.
Next: Optimizing Adacontrol, Previous: Integrating AdaControl into GNATdashboard, Up: Program Usage
This section describe utilities that are handy to use in conjunction with AdaControl.
| • pfni | ||
| • adactl_fix | ||
| • makepat.sed | ||
| • unrepr.sed |
Next: adactl_fix, Previous: Helpful utilities, Up: Helpful utilities
The convention used to refer to entities (as described in Specifying an Ada entity name) is very powerful, but it may be difficult to spell out correctly the name of some entities, especially when using the overloaded syntax.
pfni (which stands for Print Full Name Image) can be used
to get the correct spelling for any Ada entity. The syntax of
pfni is:
pfni [-sofdq] [-p <project-file>] <unit>[:<span>]
[-- <ASIS options>]
<span> ::= <line_number>
| [<first_line>]-[<last_line>]
| <line_number>:<column_number>
or
pfni -h
If called with the “-h” option, pfni prints a help message
and exits.
Otherwise, pfni prints the full name image of all identifiers
declared in the indicated unit, unless there is a “-f” (full)
option, in which case it prints the full name image of all identifiers
(i.e. including those that are used, but not declared, in the
unit). The image is printed without overloading information, unless
the “-o” option is given.
In addition, pfni prints the initial value of variables if
there is one, the range of discrete types, and the range of the
indices of array types.
The <unit> is given either as an Ada unit, or as a file name, provided the extension is “.ads” or “.adb” (as in AdaControl). If a span is given, only identifiers within the span are printed. In the first form, the span includes only the indicated line; in the second form, the span includes all lines from <first_line> to <last_line> (if omitted, they are taken as the first and last line of the file, respectively). In the third form, the span includes only the place at the specified <line_number> and <column_number>.
Normally, the source line corresponding to the names is printed above the names. The “-q” (quiet) option suppresses this.
If the “-s” option is given (or the unit is a file name with a “.ads” extension), the specification of the unit is processed, otherwise the body is processed. The “-p” option specifies the name of a project file (“.gpr” or “.adp”), and the “-d” option is the debug mode, as for AdaControl itself. ASIS options can be passed, like for AdaControl, after a “--” (but -FS is the default). See ASIS options.
As a side usage of pfni, if you are calling a subprogram that
has several overloadings and you are not sure which one is called, use
pfni with the “-o” option on that line: the program will tell
you the full name and profile of the called subprogram.
Next: makepat.sed, Previous: pfni, Up: Helpful utilities
adactl_fix is a utility that applies automatically the fixes
generated by AdaControl. See Fixing violations for details.
Next: unrepr.sed, Previous: adactl_fix, Up: Helpful utilities
This file (provided in the “src” directory) is a sed script that transforms a text file into a set of correponding regular expressions. It is useful to generate model header files. See Header_Comments.
Previous: makepat.sed, Up: Helpful utilities
This file (provided in the “src” directory) is a sed script that comments out all representation clauses. It is typically useful if you use a different compiler that accepts representation clauses not supported by GNAT.
Typically, you would copy all your sources in a different directory, copy “unrepr.sed” in that directory, then run:
sed -i -f unrepr.sed *.ads *.adb
You can now run AdaControl on the patched files. Of course, you won’t be able to check rules related to representation clauses any more...
Note that the script adds “--UNREPR ” to all representation clauses. Its effect can thus easily be undone with the following commad:
sed -i -e "s/--UNREPR //" *.ads *.adb
Next: In case of trouble, Previous: Helpful utilities, Up: Program Usage
There are many factors that may influence dramatically the speed of AdaControl when processing many units. For example, on our canonical test (same controls, same units), the extreme points for execution time were 111s. vs 13s.! Unfortunately, this seems to depend on a number of parameters that are beyond AdaControl’s control, like the relative speed of the CPU to the speed of the hard-disk, or the caching strategy of the file system.
This section will give some hints that may help you increase the speed of AdaControl, but it will not change the output of the program; you don’t really need to read it if you just use AdaControl occasionnally. This section is concerned only with the GNAT implementation of ASIS; other implementations work differently.
Bear in mind that the best strategy depends heavily on how your program is organized, and on the particular OS and hardware you are using. Therefore, no general rule can be given, you’ll have to experiment yourself. Hint: if you specify the “-v” option to AdaControl, it will print in the end the elapsed time for running the tests; this is very helpful to make timing comparisons.
Note: all options described in this section are ASIS options, i.e. they must appear last on the command line, after a “--”.
| • Tree files and the ASIS context | ||
| • Generating tree files manually | ||
| • Choosing an appropriate combination of options |
Next: Generating tree files manually, Previous: Optimizing Adacontrol, Up: Optimizing Adacontrol
Since AdaControl is an ASIS application, it is useful to explain here how ASIS works. ASIS (and therefore AdaControl) works on a set of units constituting a “context”. Any reference to an Ada entity which is not in the context (nor automatically added, see below) will be ignored; especially, if you specify to AdaControl the name of a unit which is not included in the current context, the unit will simply not be processed.
ASIS works by exploring tree files (same name as the corresponding Ada unit, with a “.adt” extension), which are “predigested” views of the corresponding Ada units. By default, the tree files are generated automatically when needed, and kept after each run, so that subsequent runs do not have to recreate them.
A context in ASIS-for-Gnat is a set of tree files. Which trees are part of the context is defined by the “-C” option:
The “-F” option specifies what to do if the program tries to access an Ada unit which is not part of the context:
Note that “-FT” is the only allowed mode, and must be specified, with the “-C1” and “-CN” options.
The default combination used by AdaControl is “-CA -FM”. A consequence of this is that the context is established by first loading all available tree files before starting the analysis, even those that are not necessary. Since tree files are often big and long to load, if you want to check a single unit and have remaining trees from a previous run, it is often more efficient to delete all “.adt” files first.
More generally, given the current speed of CPUs and the not-so-fast access time of disks, it may happen that recomputing the trees instead of loading them from disk might be faster. Only experiencing will tell you the best procedure to follow.
Next: Choosing an appropriate combination of options, Previous: Tree files and the ASIS context, Up: Optimizing Adacontrol
It is also possible to generate the tree files manually before running AdaControl. Although this mode of operation is less practical, it is recommended by AdaCore for any ASIS tool that deals with many compilation units. Some reasons why you might want to generate the tree files manually are:
To generate tree files manually, simply recompile your project with
the “-gnatct” option. This option can be passed to gnatmake
or gprbuild normally. Of course, you will need all other
options needed by your project (like the “-P” option if you are
using GNAT project files).
Tree files may be copied into a different directory if you don’t want your current directory to be cluttered by them. In this case, use the “-T” ASIS option to indicate the directory where the tree files are located.
If you chose to generate the tree files manually, you may want to specify the “-FT” ASIS option (see above) to prevent from accidental automatic recompilation.
Previous: Generating tree files manually, Up: Optimizing Adacontrol
In order to optimize the use of AdaControl, it is important to remember that reading tree files is a time-consuming operation. On the other hand, a single tree file contains not only information for the corresponding unit, but also for the specifications of all units that the given unit depends on. Moreover, our measures showed that reading an existing tree file may be slower than compiling the corresponding unit on-the-fly (but once again, YMMV).
Here are some hints to help you find the most efficient combination of options.
adactl -f rules_file.aru example -- -FT -C1 example.adt
provided the tree file already exists.
Previous: Optimizing Adacontrol, Up: Program Usage
If you encounter a problem while using AdaControl, you are very welcome to report it through our bug tracking system (under Windows, you can click on “Report problem” in the AdaControl Start menu). Please include the exact control and the unit that caused the problem, as well as the captured output of the program (with “-dx” option).
If AdaControl seems to be frozen, first make sure that it is not
simply slow (some rules may require quite a lot of time on big
units). Check for example if the size of the result file is
growing. If it appears that AdaControl is really stuck, you can
recompile it in interruptible mode (see the comments in file
framework-interrupt.adb for details). Then, if you hit Ctrl-C
in debug mode (“-d” option), AdaControl aborts with a message
telling the currently active rule and module.
Note that this interruptible mode may imply a penalty in execution time, that’s why it is not enabled by default.
Like any sophisticated piece of software, AdaControl may fail when encountering some special case of construct. ASIS may also fail occasionnally; actually, we discovered several ASIS bugs during the development of AdaControl. These were reported to ACT, and have been corrected in the wavefront version of GNAT - but you may be using an earlier version. In this case, try to upgrade to a newer version of ASIS. If an AdaControl or ASIS problem is not yet solved, AdaControl is designed in such a way that an occasionnal bug won’t prevent you from using it.
If AdaControl detects an unexpected exception during the processing of a unit (an ASIS error or an internal error), it will abandon the unit, clean up everything, and go on processing the remaining units. This way, an error due to a special case in a unit will not affect the processing of other units. AdaControl will return a Status of 10 in this case.
However, if it is run with the “-x” option (eXit on error), it will stop immediately, and no further processing will happen.
If you don’t want the garbage from a failing rule to pollute your report, you may chose to disable the rule for the unit that has a problem. See Inhibit command.
Next: Rules reference, Previous: Program Usage, Up: Top
AdaControl is about controlling rules. Rules are built in AdaControl; each rule has a name, and may require parameters. For the complete description of each rule, see Rules reference.
To run AdaControl, you need to define which rules you want to apply to your Ada units, what are the parameters, etc. In addition, you may want to define various things, like the file where the results should go, the output format, etc.
AdaControl defines a small command language which is used to describe how you want to process your units. Commands can be specified either on the command line or in a file, that we call here a rules file. Commands can also be given interactively; See Interactive mode.
| • General | ||
| • Controls | ||
| • Other commands | ||
| • Example of commands |
Next: Controls, Previous: Command language reference, Up: Command language reference
The command language is not case-sensitive, i.e. the case of the keywords, rule names, and parameters is not significant. The layout of commands is free (i.e. a command can extend over several lines, and spaces are freely allowed between syntactic elements).
Comments are allowed in and between commands. Comments begin with a “#” or a “--”, and extend to the end of the line.
Since wide characters are allowed in Ada programs, AdaControl accepts wide characters in commands as well. With GNAT, the encoding scheme is Hex ESC encoding (see the GNAT User-Guide/Reference-Manual). This is the prefered method, since few people require wide characters in programs anyway, and that keeping the default bracket encoding would not conveniently allow brackets for regular expressions, like those used by some rules. See Syntax of regular expressions.
If a syntax error is encountered in a command, an appropriate error message is output, and analysis of the command file continues in order to output all errors, but no analysis of user code will be performed.
Next: Other commands, Previous: General, Up: Command language reference
A control command is a command that declares one (or several) controls. A control defines how a rule is applied to Ada units. The syntax of a control command is as follows:
<control_command> ::= [<label> ":"] <control> {"," <control>} ";"
<control> ::= <ctrl_kind> <Rule_Name> [<parameters>]
<parameters> ::= "(" [<modifiers>] <value>
{"," [<modifiers>] <value>} ")"
<ctrl_kind> ::= "check"|"search"|"count"
If present, the label gives a name to the control(s); it will be
printed whenever each control is activated, and can be used to disable
the control(s). See Disabling controls. If no label is present,
the rule name is printed instead. The label must have the syntax of an
Ada identifier, or else the label must be included within double
quotes ("), in which case it can contain any character.
Each control consists of a <ctrl_kind> followed by a rule name, and (optionally) parameters. Some parameters may be preceded by modifiers (such as “not” or “case_sensitive”). The meaning of the rule parameters and modifiers depends on the rule.
Here are some examples of commands:
check unnecessary_use_clause;
All_Imports: search pragmas (Import);
"Why do you need that?": check entities (Unchecked_Conversion,
all 'Address);
Specifying several controls with the same label is a shorthand which is equivalent to specifying the same label for several controls. It is handy when the label is long, and/or to stress that several controls are part of the same programming rule. For example:
"Check why this obsolete stuff is still used": check entities (obsolete_unit_1), -- Note comma here! check instantiations (some_obsolete_generic);
| • Control kinds and report messages | ||
| • Parameters | ||
| • Multiple controls | ||
| • Disabling controls |
Next: Parameters, Previous: Controls, Up: Controls
There are three control kinds: “check”, “search”, and “count”.
“Check” is intended to search for rules that must be obeyed in your programs. Normally, if a “Check” control fails, you should fix the program. “Search” is intended to report some situations, but you should consider what to do on a case-by-case basis. Roughly, use “check” when you consider that the failure of the control is an error, and “search” when you consider it as a warning. AdaControl will exit with a status of 1 if any “Check” control is triggered, and a status of 0 if only “Search” controls were triggered (or no control was triggered at all).
“Count” works like “Search”, but instead of printing a message for each control which is triggered, it simply counts occurrences and prints a summary at the end of the run. There is a separate count for each control label (or if no label is given, the rule name is taken instead); if you give the same label to different controls, this allows you to accumulate the counts.
A report message (except for the final report of “count”) comprises the following elements:
The formatting of the report message depends on the format option, which can be selected with the “-F” command-line option or the “set format” command.
If the format is “Gnat” (the default) or “Gnat_Short”, items are separated by ’:’; this is the same format as the one used by GNAT error messages. Editors (like Emacs or GPS) that recognize this format allow you to go directly to the place of the message by clicking on it. In order to avoid too long messages, only the label appears, unless there is none, in which case it is replaced with the rule name.
If the format is “CSV” or “CSV_Short”, items are separated by ’,’ and surrounded by double quotes. This is the “Comma Separated Values” format, which can be read by any known spreadsheet program, except Excel(tm) by default, which uses the semicolon and not the comma to separate fields. Therefore, the formats “CSVX” and “CSVX_Short” do the same thing, but using semi-colons (’;’) instead of commas. Both the label (replaced by an empty column if there is none) and the rule name appear. Note that when an output file is created in one of the “CSV” formats, a title line is issued as the first line, following normal CSV convention.
If the format is “Source” or “Source_Short”, the offending source line is output, and the message is output behind it, with a “!” pointing to the exact location of the problem.
If the format is “None”, no error message is output at all. This is useful when only the return code of running AdaControl is desired (just to check if a program is OK or not). Note that this does not prevent the output of statistics, since these are under control of the “-S” option or the “set statistics” command. In this case, statistics are output in CSVX format, since asking for statistics with a “none” format is mainly useful for analysing the statistics with a spreadsheet program.
With recent versions of GNAT, the file name includes the full path of the source file. If the “_Short” form of the format option is used, the file name is stripped from any path. This can make it easier to compare the results of controlling units from various directories. Note that with older versions of GNAT, the file name never includes the full path, and the “_Short” form of the format option has no effect.
After each run (see Go command), statistics may be output, depending on the statistics level which is set with the “-S” option or the “set statistics” command. The meaning of the various levels is as follows:
Next: Multiple controls, Previous: Control kinds and report messages, Up: Controls
Most rules accept parameters. Parameters can be:
A numerical value is given with the syntax of an Ada integer or real literal (underscores and exponents are allowed as in Ada). Based literals are supported for integer values; if somebody can justify a need for supporting them for reals, we’ll be happy to add this feature later...
A character string is given within double quotes “"”. As usual, quotes appearing within the string are doubled. The tilde character (“~”) can be used as a replacement delimiter, but the same character must be used at both ends of the string. The latter has been chosen as a character not used by the various shells, and can be useful to pass quoted strings from parameters on the command line (unfortunately, we could not use the percent (“%”) sign, because it plays a special role in DOS/Windows).
An Ada entity name is the full name (prefixed with the names of all units that include it) of something declared in a program. It can be followed by overloading information, in order to uniquely identify the Ada entity. If an Ada entity is overloaded and no overloading information is provided, the rule is applied to all (overloaded) Ada entities that match the name. Alternatively, it can be “all” followed by a simple name, in wich case it applies to all entities with that name. See Specifying an Ada entity name for the full description of the syntax. Here are some examples of entity names:
Ada.Text_IO.Put -- All Put defined in Ada.Text_IO
Ada.Text_IO.Put{Standard.Character} -- The Put on Character
all Put -- All Put
Standard.Integer'Image -- The 'Image function on Integer
all 'Image -- All 'Image functions
Next: Disabling controls, Previous: Parameters, Up: Controls
Most rules can be used in more than one control (with different parameters). There is no difference between a single or a multiple configuration rule use: outputs, efficiency, etc. are the same.
The following command files produce an identical configuration:
Search Pragmas (Pure, Elaborate_All);
and
Search Pragmas (Pure); Search Pragmas (Elaborate_All);
However, the second form can be used to give different labels. Consider:
Search Pragmas (Pure); No_Elaborate: Search Pragmas (Elaborate_All);
The messages for pragma Pure will contain “PRAGMAS”, while
those for Elaborate_All will contain “No_Elaborate”. If a
disabling comment mentions pragmas, it will disable both controls,
but a disabling comment that mentions No_Elaborate will disable
only the second one.
Previous: Multiple controls, Up: Controls
It is possible to disable controls on parts of the source code by
placing markers in the source code. A marker is an Ada comment, where
the comment mark (--) is immediately followed by the special
tag “##” (by default).
There are two kinds of markers: block markers and line markers. Both kinds specify a list of controls to disable/re-enable. A list of controls is a list of rule names (to disable/re-enable all controls on the indicated rule(s)) or control labels (to disable/re-enable all controls with that label), separated by spaces. Alternatively, the list of controls can be the word “all” to disable/re-enable all controls.
In a “--##” line, everything appearing after another “##”
tag (by default) is ignored. This allows the insertion of a comment
explaining why the control is disabled at that point.
Both tags can be changed with the “set” command. See Set command.
A control is disabled from a “rule off” marker that applies to it until a “rule on” marker that applies to it. If there is no appropriate “rule on” marker, the control is disabled up to the end of file.
Syntax:
--## rule off <control_list> Ada code block --## rule on <control_list>
Ex:
--## rule off rule1 rule2 ## Authorized by QA ref 1234 I := I + 1; Proc (I); --## rule on rule2
The “Rule_File_Off” command can be used to start units whose file name matches a given pattern in the “disabled” state for some or all rules. See Rule_File_Off command.
A control is disabled only for the line where a marker that applies to it appears.
Syntax:
Ada code line --## rule line off <rule_list>
Ex:
I := I + 1; --## rule line off rule3 rule_label_1
Conversely, it is possible to re-enable a control for just the current line in a block where it is disabled:
Syntax:
Ada code line --## rule line on <rule_list>
Ex:
--## rule off rule1 rule2 ... I := I + 1; --## rule line on rule2
Since the disabling is based on special comments, there is a conflict with the rule “header_comments” which is based on the content of comments. Line disabling is not possible with this rule, and block disabling needs special care. See Header_Comments.
Next: Example of commands, Previous: Controls, Up: Command language reference
In addition to controls, AdaControl recognizes a number of commands. Although these commands are especially useful when using the interactive mode (see Interactive mode), they can be used in command files as well.
| • Go command | ||
| • Quit command | ||
| • Message command | ||
| • Help command | ||
| • Clear command | ||
| • Set command | ||
| • Source command | ||
| • Rule_File_Off command | ||
| • Inhibit command |
Next: Quit command, Previous: Other commands, Up: Other commands
This command starts processing of the controls that have been specified.
Syntax:
go;
Controls are not reset after a “go” command; for example, the following program:
search entities (pack1); go; search entities (pack2); go;
will first output all usages of Pack1, then all usages of both
Pack1 and Pack2. See Clear command to reset
controls.
If not in interactive mode, a “go” command is automatically added at the end, therefore it is not required in command files.
Next: Message command, Previous: Go command, Up: Other commands
This command terminates AdaControl.
Syntax:
quit;
If given in a file, all subsequent commands will be ignored. This command is really useful only in interactive mode. See Interactive mode.
Next: Help command, Previous: Quit command, Up: Other commands
This command prints a message on the output file.
Syntax:
message ["<any string>"] [pause];
The length of the message is limited to 250 characters; if no message is given, it defaults to the empty string. If the word “pause” (case irrelevant) is specified after the message (if any), AdaControl will wait for the user to press the Return key before proceeding.
Note that the message is syntactically a string, and must therefore be quoted (double quotes).
Next: Clear command, Previous: Message command, Up: Other commands
This command prints various informations about the rules and AdaControl itself.
Syntax:
Help [<help_item> {,<help_item>}]
<Help_Item> ::=<keyword> | <rule name> | variables ["<pattern>"]
<keyword> ::= all | commands | license | list | options |
rules | version
Without any argument, this command prints a summary of all commands and rule names. If given one or more keywords or rule names, it prints the corresponding help message. See Getting help for the details.
Next: Set command, Previous: Help command, Up: Other commands
This command command clears (i.e. removes) controls that have been previously given.
Syntax:
Clear all | <rule name>{,<rule name>} ;
The command clears all controls given for the indicated rules, or for
all rules if the all keyword is given. Rule variables
(see Set command) associated to cleared rules are returned to
their default values. For example, the following program:
search entities (pack1); go; clear all; search entities (pack2); go;
will first output all usages of Pack1, then all usages of
Pack2. Without the “clear all” command, the second “go”
would output all usages of Pack1 together with all usages of
Pack2.
Next: Source command, Previous: Clear command, Up: Other commands
This command sets various parameters of AdaControl.
Syntax:
set Format Gnat|Gnat_Short|CSV|CSV_Short|Source|Source_short|None;
set Check_Key|Search_Key "<value>"
set Max_Errors [min|max] [<value>];
set Max_Messages [min|max] [<value>];
set Output|New_Output <output file>;
set Fixes_Gen Check|Search|None
set Statistics [min|max] <level>;
set Tag1|Tag2 "<value>";
set Trace <trace file>;
set Debug|Exit_On_Error|Verbose|Warning|Warning_As_Error
On|Off;
set Timing On|Off|Global
set Ignore On|Off|Inverted;
set <Rule_Name>.<Variable> [min|max] <Value>
When a parameter has an integer value, it can be preceded with the keywords “min” or “max”. If present, it indicates that the parameter should be set to at least (respectively at most) the indicated value, i.e. if the current value of the parameter is greater (respectively smaller) than the given value, it is not changed. This can be especially useful in rule files that are sourced from other rules files, where a value for the parameter has been previously set.
-- Set statistics to level 2, unless a higher level is already set set statistics min 2;
The “set format” command selects the output format for the messages, like the “-F” option; see Control kinds and report messages for details.
The “set check_key” command defines a string which is used in place of “Error” in messages issued by a “check” control. Similarly, the “set search_key” command defines a string which is used in place of “Found” in messages issued by a “search” control. This can be useful when AdaControl is used, for example, to detect places where manual inspection is required; having the word “Error” in the message could be misleading to the persons in charge of the review. Note however that if you set these keys, the GPS interface will not be able to recognize properly the messages.
The “set max_errors” and “set max_messages” limit the output of AdaControl, like the “-m” and “-M” options; see Output limits for details. If no <value> is given after the command name, the corresponding limitation is removed.
The “set output” and “set new_output” commands redirect the output
of subsequent controls to the indicated file. If the string
console (case irrelevant) is given as the <output file>, output
is redirected to the console.
The “set fixes_gen” command controls the generation of fixes indications, like the “-G” option; see Output format for details.
The “set new_output” always create a new file (or overwrites an existing file with the same name).
The “set output” command appends if the file exists, unless the “-w” option is given, in which case it is overwritten. However, the file is overwritten only the first time it is mentionned in an “output” command. This means that you can switch forth and back between two output files, all results from the same run will be kept. Note however that for this to work, you need to specify the output files exactly the same way: if you specify it once as “result.txt”, and then as “./result.txt”, the second one will overwrite the first one.
The “set statistics” command sets the statistics level, like the “-S” option; see Control kinds and report messages for details.
The “set Tag1|Tag2” command changes the tags used to disable (or
enable) rules. “Tag1” is the string that appears immediately after
the comment indicator (--), and “tag2” is the tag that
terminates the special comment. Note that these tags must be given as
strings (in quotes) and that case is relevant. See Disabling controls for details.
The “set trace” command redirects the trace messages of the
“-d” option to the indicated file. If the string console
(case irrelevant) is given as the <trace file>, trace messages are
redirected to the console. As with the “-t” option, if the file
exists, output is appended to it.
The “set Debug|Exit_On_Error|Verbose|Warning|Warning_As_Error” command activates (“on”) or deactivates (“off”) options. “Debug” corresponds to the “-d” option, “Exit_On_Error” to the “-x” option, “Ignore” to the “-i” option, “Timing” to the “-T” option, “Verbose” to the “-v” option, “Warning” to the “-E” option, and “Warning_As_Error” to the “-e” option. See Verbose and debug mode, Exit on error, Treatment of warnings, Output format, and Local disabling control for details.
The “set Timing” command activates (“on”) or deactivates (“off”) the printing of the time spent in each rule after each “go” command. If set to “global” instead of “on”, the timings are accumulated over all “go” commands, and output when the program terminates.
The “set Ignore” command governs handling of disabled messages (see Disabling controls). In default mode (“set Ignore Off”), disabled messages are not printed. When set to “on” (“set Ignore On”), all messages are printed, including those that are disabled. Setting this option can result in considerable speed-up of the printing of messages. When set to “Inverted” (“set Ignore Inverted”), only disabled messages are printed. This is useful to check which messages have been disabled.
Some rules may also have user-settable global variables that affect their behaviour; the last form of the “set” command allows changing their value. The variable name is of the form of a qualified name (i.e. “rule.var”), and the value depends on the variable. The description of the variables (if any) and appropriate values is given for each rule.
Next: Rule_File_Off command, Previous: Set command, Up: Other commands
This command inputs commands from another file.
Syntax:
Source <input file>;
Commands are read and executed from the indicated file, then control is returned to the place after the “source” command. There is no restriction on the content of the sourced file; especially, it may itself include other “source” commands.
If <input file> is a relative file path, it is taken relatively to the
file where the “source” command is given. Especially, if no path is
specified, the sourced file will be taken from the same directory as
the sourcing file (irrespectively of where the command is being run
from). If the file is not found there, it is searched on the path given
by the environment variable ADACTL_PATH.
The default extension is .aru, i.e. if <input file> is not
found as given, AdaControl will retry the same name with .aru
appended. It is a syntax error if the file is not found either.
If the string console (case irrelevant) is given as the <input
file>, commands are read from the console until a “quit” command is
given. This command is of course useful only from files, and allows to
pass temporarily control to the user in interactive mode.
Next: Inhibit command, Previous: Source command, Up: Other commands
This command changes the initial disabled state to “off” for files that match a given pattern. See Disabling controls.
Syntax:
Rule_file_off "<pattern>" all | <rule name> {, <rule name>}
Messages from files whose (full path) name matches the given <pattern>
are initially disabled, like if a “--##rule off” comment had been
given before the first line of the file. The pattern is given using
the full Regexp syntax, not the file pattern matching of the
system. see Syntax of regular expressions for details.
If “all” is given, messages for all rules are disabled, otherwise messages are disabled only for the given rule(s).
Example:
-- Disable all messages from units located in the -- "external_components" directory: rule_file off "/external_components/" all -- Disable rules expressions and statements for bodies of unit -- Compo and children (in Gnat file notation): rule_file_off "compo(-.*)*\.adb$" expressions, statements
Unlike the regular “--##rule off” comment, it is not possible to
disable a control according to its label, only rule names can be
given.
This command works on file names, not on logical Ada units.
Rules can be re-enabled if the file contains a matching “--##rule on”
comment.
Previous: Rule_File_Off command, Up: Other commands
This command prevents execution of certain controls on particular units.
Syntax:
Inhibit <rule name>|all ([all] <unit> {,[all] <unit>});
Controls refering to the given rule (or all rules if “all” is specified in place of a rule name) for the indicated unit(s) are not performed. In addition, if “all” is specified in front of the unit name, the unit will not be accessed at all, even from rules that follow call graphs, and could thus access this unit while analyzing other units.
There are several reasons why you might want to inhibit a control of a rule for certain units:
The “all” option for a unit is intended for the last case, to prevent ASIS bugs from spoiling any unit that calls something from an offending unit.
This command prevents the unit from being analyzed, and it is not possible to “uninhibit” it, unlike the “Rule_File_Off” command (see Rule_File_Off command) that simply turns off messages. Note also that the “Rule_File_Off” command works on file name patterns while the “inhibit” command works on Ada units.
Previous: Other commands, Up: Command language reference
Below is an example of a file with multiple commands:
message "Searching Unchecked_Conversion"; search entitities (ada.unchecked_conversion); set output uc_usage.txt; go; clear all; message "Searching 'Address"; search entities (all 'Address); set output address_usage.txt; go;
This file will output all usages of Ada.Unchecked_Conversion
into the file uc_usage.txt, then output all usages of the
'Address attribute into the file
address_usage.txt. Messages are output to tell the user about
what’s happenning.
Next: Examples of using AdaControl for common programming rules, Previous: Command language reference, Up: Top
This chapter describes each rule currently provided by
AdaControl. Note that the rules directory of the distribution
contains a file named verif.aru that contains an example of a
set of rules appropriate to check on almost any software.
A general limitation applies to all rules. AdaControl is a static checking tool, and therefore cannot check usages that depend on run-time values. For example, it is not possible to check rules applying to an entity when this entity is aliased and accessed through an access value, or rules applying to subprogram calls when the call is a dispatching call.
Next: Actual_Parameters, Previous: Rules reference, Up: Rules reference
This rule controls functions that may not terminate normally, i.e. where
Program_Error could be raised due to reaching the end of the
function without encountering a return statement.
<control_kind> abnormal_function_return;
The rule controls that the sequence of statements of each function body, as well as each of its exception handlers, ends with:
return statement (including extended return statements)
raise statement (or equivalently, a call to
Ada.Exceptions.Raise_Exception or
Ada.Exceptions.Reraise_Occurrence);
pragma No_Return;
if statement that includes an else path, and
where the last statement of every path is one of these;
case statement where the last statement of every path is
one of these.
loop statement (not for or
while) without any exit or goto
statement transfering control outside of the loop.
This is a sufficient (but of course not necessary) condition to ensure
that no function raises Program_Error due to reaching the end
of its statements without encountering a return.
This rule can be specified only once.
Ex:
check abnormal_function_return;
This rule checks that a function always returns correctly, but does not
prevent multiple return statements in functions. If you want
to ensure that there is exactly one return statement in functions,
and that this statement is always the last one, use this rule together with
the rule statements(function_return).
See Statements.
It is possible to exit from an extended return statement with an
exit or goto statement. If this happens, the
return statement is not considered a proper return statement, and an
appropriate message is issued.
Next: Allocators, Previous: Abnormal_Function_Return, Up: Rules reference
This rule checks properties of actuals provided to calls or instantiations.
<control_kind> actual_parameters (<subrule>, <place>, <formal>
{, <actual>});
<subrule>::= default_used | default_not_used | default_positional |
entity
<place> ::= <entity> | calls | instantiations
<formal> ::= <formal name> | all
<actual> ::= [all] <entity>
The first parameter is a subrule keyword. All subrules check properties of an actual value of a call or instantiation. The called (or instantiated) entity is given by <place>, which is either an explicit entity specification, “calls” if all calls are controlled, or “instantiations” if all instantiations are controlled. The check applies to parameters whose name