AdaControl User Guide V1.21r6b

Next: , Previous: , Up: (dir)  

AdaControl User Guide

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: , Previous: , Up: Top  

1 Introduction

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.


Next: , Previous: , Up: Introduction  

1.1 Features

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: , Previous: , Up: Introduction  

1.2 Support

1.2.1 Commercial support

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.

1.2.2 Other support

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/.

1.2.3 Your support to us, too!

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: , Previous: , Up: Introduction  

1.3 History

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: , Up: Introduction  

1.4 References

  1. “On the benefits for industrials of sponsoring free software development”, Ada User Journal, Volume 26, number 4, december 2005

    http://www.adalog.fr/publicat/Free-software.pdf

  2. “A Comparison of Industrial Coding Rules”, Ada User Journal, Volume 29, number 4, december 2008

    http://www.adalog.fr/publicat/coding-rules.pdf

  3. “A Methodology for Avoiding Known Compiler Problems Using Static Analysis”, proceedings of the ACM SIGAda Annual International Conference (SIGAda 2010)

    http://dl.acm.org/authorize?316395


Next: , Previous: , Up: Top  

2 Installation

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.


Next: , Previous: , Up: Installation  

2.1 Building and installing AdaControl from source

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.

2.1.1 Getting the correct version of the sources for your Gnat version

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.

2.1.2 Prerequisites

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.

2.1.3 Build and install with installer (Windows)

Run the installer (adactl_src-setup.exe). This will automatically build and install AdaControl, no other installation is necessary.

2.1.4 Build and install with project file

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

2.1.5 Build and install with Makefile

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.

2.1.6 Manual installation

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.

2.1.7 Build with a compiler other than GNAT

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.

2.1.8 Testing AdaControl

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:

2.1.9 Customizing AdaControl

If there are some rules that you are not interested in, it is very easy to remove them from AdaControl:

  1. In the 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.
  2. Recompile framework-plugs.adb. There will be error messages about unknown procedure calls. Comment out the corresponding lines.
  3. Compile AdaControl normally. That’s all!

It is also possible to add new rules to AdaControl. If your favorite rules are not currently supported, you have several options:

  1. If you have some funding available, please contact info@adalog.fr. We’ll be happy to make an offer to customize AdaControl to your needs.
  2. If you don’t have funding, but have some knowledge of ASIS programming, you can add the rule yourself. We have made every effort to make this as simple as possible. Please refer to the AdaControl programmer’s manual for details. If you do so, please send your rules to rosen@adalog.fr, and we’ll be happy to integrate them in the general release of AdaControl to make them available to everybody.
  3. If you have good ideas, but don’t feel like implementing them yourself (nor financing them), please send a note to rosen@adalog.fr. We will eventually incorporate all good suggestions, but we can’t of course commit to any dead-line in that case.

Next: , Previous: , Up: Installation  

2.2 Installing an executable distribution

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: , Previous: , Up: Installation  

2.3 Installing support for AdaGide

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: , Up: Installation  

2.4 Installing support for GNATdashboard integration

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: , Previous: , Up: Top  

3 Program Usage

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:

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: , Previous: , Up: Program Usage  

3.1 Command line parameters and options


Next: , Previous: , Up: Command line parameters and options  

3.1.1 Input units

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: , Previous: , Up: Command line parameters and options  

3.1.2 Commands

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: , Previous: , Up: Command line parameters and options  

3.1.3 Output file

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: , Previous: , Up: Command line parameters and options  

3.1.4 Output format

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: , Previous: , Up: Command line parameters and options  

3.1.5 Output limits

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: , Previous: , Up: Command line parameters and options  

3.1.6 Project files

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.

3.1.6.1 Tip

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: , Previous: , Up: Command line parameters and options  

3.1.7 Local disabling control

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: , Previous: , Up: Command line parameters and options  

3.1.8 Verbose and debug mode

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: , Previous: , Up: Command line parameters and options  

3.1.9 Treatment of warnings

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: , Previous: , Up: Command line parameters and options  

3.1.10 Exit on error

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: , Up: Command line parameters and options  

3.1.11 ASIS 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: , Previous: , Up: Program Usage  

3.2 Return codes

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: , Previous: , Up: Program Usage  

3.3 Environment variable and default settings

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: , Previous: , Up: Program Usage  

3.4 Fixing violations

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.

3.4.1 Interactive fixing

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.

3.4.2 Automatic fixing

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.

3.4.2.1 Conflicts

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.

3.4.3 How to proceed

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!

3.4.4 Tip

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”).

3.4.5 A word of caution

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: , Previous: , Up: Program Usage  

3.5 Interactive mode

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: , Previous: , Up: Program Usage  

3.6 Other execution modes

In addition to normal usage, AdaControl features special options to ease its use; no Ada unit is analyzed when using these options.


Next: , Previous: , Up: Other execution modes  

3.6.1 Getting help

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: , Previous: , Up: Other execution modes  

3.6.2 Checking commands syntax

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: , Up: Other execution modes  

3.6.3 Generating a units list

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.

3.6.3.1 Limitation

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: , Previous: , Up: Program Usage  

3.7 Running AdaControl from GPS

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.


Next: , Previous: , Up: Running AdaControl from GPS  

3.7.1 The AdaControl menu and buttons

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: , Previous: , Up: Running AdaControl from GPS  

3.7.2 Contextual menu

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: , Previous: , Up: Running AdaControl from GPS  

3.7.3 AdaControl switches

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).

3.7.3.1 Files

This section controls the definition of various files used by AdaControl.

3.7.3.2 Processing

This section offers options that control how units are processed.

3.7.3.3 Debug

This section controls the debugging options of AdaControl.

3.7.3.4 Output

This section offers options that control where and how the output of AdaControl is displayed.

3.7.3.5 ASIS

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: , Previous: , Up: Running AdaControl from GPS  

3.7.4 AdaControl preferences

There is an entry for AdaControl in the “edit/preferences” menu:


Next: , Previous: , Up: Running AdaControl from GPS  

3.7.5 AdaControl language

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: , Previous: , Up: Running AdaControl from GPS  

3.7.6 AdaControl help

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: , Up: Running AdaControl from GPS  

3.7.7 Caveat

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: , Previous: , Up: Program Usage  

3.8 Running AdaControl from AdaGide

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:


Next: , Previous: , Up: Program Usage  

3.9 Integrating AdaControl into GNATdashboard

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: , Previous: , Up: Program Usage  

3.10 Helpful utilities

This section describe utilities that are handy to use in conjunction with AdaControl.


Next: , Previous: , Up: Helpful utilities  

3.10.1 pfni

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: , Previous: , Up: Helpful utilities  

3.10.2 adactl_fix

adactl_fix is a utility that applies automatically the fixes generated by AdaControl. See Fixing violations for details.


Next: , Previous: , Up: Helpful utilities  

3.10.3 makepat.sed

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: , Up: Helpful utilities  

3.10.4 unrepr.sed

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: , Previous: , Up: Program Usage  

3.11 Optimizing Adacontrol

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 “--”.


Next: , Previous: , Up: Optimizing Adacontrol  

3.11.1 Tree files and the ASIS context

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: , Previous: , Up: Optimizing Adacontrol  

3.11.2 Generating tree files manually

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: , Up: Optimizing Adacontrol  

3.11.3 Choosing an appropriate combination of options

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.


Previous: , Up: Program Usage  

3.12 In case of trouble

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).

3.12.1 AdaControl stuck in infinite loop

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.

3.12.2 AdaControl or ASIS failure

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: , Previous: , Up: Top  

4 Command language reference

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.


Next: , Previous: , Up: Command language reference  

4.1 General

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: , Previous: , Up: Command language reference  

4.2 Controls

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);

Next: , Previous: , Up: Controls  

4.2.1 Control kinds and report messages

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: , Previous: , Up: Controls  

4.2.2 Parameters

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: , Previous: , Up: Controls  

4.2.3 Multiple 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: , Up: Controls  

4.2.4 Disabling 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.

4.2.4.1 Block disabling

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.

4.2.4.2 Line disabling

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

4.2.5 Limitation

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: , Previous: , Up: Command language reference  

4.3 Other commands

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.


Next: , Previous: , Up: Other commands  

4.3.1 Go command

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: , Previous: , Up: Other commands  

4.3.2 Quit command

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: , Previous: , Up: Other commands  

4.3.3 Message command

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: , Previous: , Up: Other commands  

4.3.4 Help command

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: , Previous: , Up: Other commands  

4.3.5 Clear command

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: , Previous: , Up: Other commands  

4.3.6 Set command

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: , Previous: , Up: Other commands  

4.3.7 Source command

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: , Previous: , Up: Other commands  

4.3.8 Rule_File_Off command

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

4.3.8.1 Tips

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: , Up: Other commands  

4.3.9 Inhibit command

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.

4.3.9.1 Tip

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: , Up: Command language reference  

4.4 Example of commands

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: , Previous: , Up: Top  

5 Rules reference

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: , Previous: , Up: Rules reference  

5.1 Abnormal_Function_Return

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.

5.1.1 Syntax

<control_kind> abnormal_function_return;

5.1.2 Action

The rule controls that the sequence of statements of each function body, as well as each of its exception handlers, ends with:

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;

5.1.3 Tips

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: , Previous: , Up: Rules reference  

5.2 Actual_Parameters

This rule checks properties of actuals provided to calls or instantiations.

5.2.1 Syntax

<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>

5.2.2 Action

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