5. Miscellaneous Topics

  1. 5.1. Fine Control of Included Files
  2. 5.2. Protection Macros
  3. 5.3. Index Printing
  4. 5.4. Environment Generation
  5. 5.5. TDF Library Building

In this section we round up a few miscellaneous topics.

5.1. Fine Control of Included Files

The +IMPLEMENT and +USE commands described in section 3.2 are capable of further refinement. Normally each such command is translated into a corresponding inclusion command in both the include and source output files. Occasionally this is not desirable - in particular the inclusion in the source output file can cause problems during TDF library building. For this reason the tspec syntax has been extended to allow for fine control of the output corresponding to +IMPLEMENT and +USE commands. This takes the forms:

+IMPLEMENT "api" (key) ;
+IMPLEMENT "api", "header" (key) ;
+IMPLEMENT "api", "header", "subset" (key) ;

with corresponding forms for +USE. key specifies which output files the inclusion commands should appear in. It can be:

KeyOuput files
??Neither output file
!?Include output file only
?!Source output file only
!!Both output files (default)

The second refinement comes from the fact that APIs fall into two categories - the base APIs, such as c/c89, posix and xpg3, and the extension APIs, such as x11, the X Windows API. The latter can be used to extend the former, so that we can form c/c89 plus x11, posix plus x11, and so on. Base APIs may be distinguished in tspec by including the command:

+BASE_API ;

in their master.ts file. Occasionally, in an extension API, we may wish to include a version of a header from the base API, but, because this base API is not fixed, not be able to use a simple +USE command. Instead the special form:

+USE ( "api" ), "header" ;

is provided for this purpose (this is the only permitted form). It indicates that tspec should use the api version of header for checking purposes, but allow the inclusion of the version from the base API in normal use.

5.2. Protection Macros

Each include output file is surrounded by a construct of the form:

#ifndef MACRO
#define MACRO
....
#endif /* MACRO */

to protect it against multiple inclusions. Normally tspec will generate the macro name, MACRO, but it can be set using the PROTECT file property (see section 5.4). Setting PROTECT to the empty string suppresses the protection construct altogether. (Also see section 5.1.)

5.3. Index Printing

If it is invoked with the -i command-line option, instead of creating its output file, tspec prints an index of all the objects it has read to the standard output. This information includes the external token name associated with the object, whether the object is implemented or used, and where in the API description it is defined. It also includes a brief description of the object. It is intended that these indexes should be usable as quick reference guides to the underlying APIs.

5.4. Environment Generation

When invoked with the -y command-line option, tspec outputs an environment file suitable for use with the tcc frontend. This contains a description of the API (per its $INFO field) which can be presented to the user, along with internal configuration and library dependencies for how tcc is to invoke that API.

5.5. TDF Library Building

As was explained in reference 1, the #pragma token headers output by tspec are used for two purposes - checking applications against the API during normal compilation and checking implementations against the API during TDF library building. This dual use does necessitate some extra work for tspec. It is not always possible to use exactly the same code in the two cases (usually because the C rules on, for example, structure definitions get in the way during library building). tspec uses a standard macro, __BUILDING_LIBS, to distinguish between the two cases. It is assumed to be defined if and only if library building is taking place. tspec descriptions can access this macro directly using ~building_libs (see section 5.1).

The actual library building process consists of compiling the #pragma token descriptions of the objects comprising the API along with the implementation of that API from the system headers (or wherever). This creates the local token definitions for this API, which may be stored in a token library. To facilitate this process tspec creates the source output files for each implemented header api:header containing something like:

#pragma implement interface <../api/header>
#include <header>

There are other methods whereby the source output file may be changed into a set of token definitions. For example, consider:

$METHOD = "TNC" ;
+MACRO double fl_abs ( double ) ;
%%%
	( make_tokdef fl_abs ( exp x ) exp
			( floating_abs impossible x ) )
%%%

The include output file will specify a token fl_abs which takes a double and returns a double. The TNC method tells MAKE_LIBS that the source output file, which will just contain the quoted text:

( make_tokdef fl_abs ( exp x ) exp
	( floating_abs impossible x ) )

is an input file for the TDF notation compiler, tnc (see reference 2). Thus we have defined a token which directly accesses the TDF floating_abs construct.