Subversion Repositories tendra.SVN

Rev

Blame | Last modification | View Log | RSS feed

<!-- Crown Copyright (c) 1998 -->
<HTML>
<HEAD>
<TITLE>
tspec - An API Specification Tool   
</TITLE>
</HEAD>

<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#400080" ALINK="#FF0000">
<H1>tspec - An API Specification Tool</H1>
<H3>January 1998</H3>
<IMG SRC="../images/no_next.gif" ALT="next section">
<IMG SRC="../images/no_prev.gif" ALT="previous section">
<IMG SRC="../images/no_top.gif" ALT="current document">
<A HREF="../index.html"><IMG SRC="../images/home.gif" ALT="TenDRA home page">
</A>
<IMG SRC="../images/no_index.gif" ALT="document index"><P>
<HR>
<DL>
<DT><A HREF="#Intro"><B>1</B> - Introduction</A><DD>
<DT><A HREF="#Overview"><B>2</B> - Overview of tspec</A><DD>
<DL>
<DT><A HREF="#Levels"><B>2.1</B> - Specification Levels</A><DD>
<DT><A HREF="#Input"><B>2.2</B> - Input Layout</A><DD>
<DT><A HREF="#Output"><B>2.3</B> - Output Layout</A><DD>
<DT><A HREF="#Copyright"><B>2.4</B> - Copyright Messages</A><DD>
<DT><A HREF="#Options"><B>2.5</B> - Command-line Options</A><DD>
</DL>
<DT><A HREF="#Structure"><B>3</B> - Specifying API Structure</A><DD>
<DL>
<DT><A HREF="#Subset"><B>3.1</B> - +SUBSET</A><DD>
<DT><A HREF="#Impl"><B>3.2</B> - +IMPLEMENT and +USE</A><DD>
</DL>
<DT><A HREF="#Objects"><B>4</B> - Specifying Objects</A><DD>
<DL>
<DT><A HREF="#S41"><B>4.1</B> - Object Names</A><DD>
<DT><A HREF="#Func"><B>4.2</B> - +FUNC</A><DD>
<DT><A HREF="#Exp"><B>4.3</B> - +EXP and +CONST</A><DD>
<DT><A HREF="#Macro"><B>4.4</B> - +MACRO</A><DD>
<DT><A HREF="#Statement"><B>4.5</B> - +STATEMENT</A><DD>
<DT><A HREF="#Define"><B>4.6</B> - +DEFINE</A><DD>
<DT><A HREF="#Type"><B>4.7</B> - +TYPE</A><DD>
<DT><A HREF="#Typedef"><B>4.8</B> - +TYPEDEF</A><DD>
<DT><A HREF="#Field"><B>4.9</B> - +FIELD</A><DD>
<DT><A HREF="#Nat"><B>4.10</B> - +NAT</A><DD>
<DT><A HREF="#Enum"><B>4.11</B> - +ENUM</A><DD>
<DT><A HREF="#Token"><B>4.12</B> - +TOKEN</A><DD>
</DL>
<DT><A HREF="#Others"><B>5</B> - Other tspec Constructs</A><DD>
<DL>
<DT><A HREF="#If"><B>5.1</B> - +IF, +ELSE and +ENDIF</A><DD>
<DT><A HREF="#Text"><B>5.2</B> - Quoted Text</A><DD>
<DT><A HREF="#Comment"><B>5.3</B> - C Comments</A><DD>
<DT><A HREF="#Properties"><B>5.4</B> - File Properties</A><DD>
</DL>
<DT><A HREF="#S6"><B>6</B> - Miscellaneous Topics</A><DD>
<DL>
<DT><A HREF="#FineImpl"><B>6.1</B> - Fine Control of Included Files</A><DD>
<DT><A HREF="#Protect"><B>6.2</B> - Protection Macros</A><DD>
<DT><A HREF="#Index"><B>6.3</B> - Index Printing</A><DD>
<DT><A HREF="#Libraries"><B>6.4</B> - TDF Library Building</A><DD>
</DL>
<DT><A HREF="#S7"><B>7</B> - Changes in tspec 2.0</A><DD>
<DT><A HREF="#S8"><B>8</B> - References</A><DD>
</DL>
<HR>

<H2><A NAME="Intro">1. Introduction</A></H2>
<P>
As explained in reference 1, TDF may be regarded as an abstract target
machine which can be used to facilitate the separation of target independent
and target dependent code which characterises portable programs. An
important aspect of this separation is the Application Programming
Interface, or API, of the program. Just as, for a conventional machine,
the API needs to be implemented on that machine before the program
can be ported to it, so for that program to be ported to the abstract
TDF machine, an &quot;abstract implementation&quot; of the API needs
to be provided.   
<P>
But of course, an &quot;abstract implementation&quot; is precisely
what is provided by the API specification - it is an abstraction of
all the possible API implementations. Therefore the TDF representation
of an API must reflect the API specification. As a consequence, compiling
a program to the abstract TDF machine is to check it against the API
specification rather than, as with compiling to a conventional machine,
against at best a particular implementation of that API.   
<P>
In this document we address the problem of how to translate a standard
API specification into its TDF representation, by describing a tool,
<CODE>tspec</CODE>, which has been developed for this purpose.   
<P>
The low level form which is used to represent APIs to the C to TDF
producer is the <CODE>#pragma token</CODE> syntax described in reference
3. However this is not a suitable form in which to describe API specifications.
The <CODE>#pragma token</CODE> syntax is necessarily complex, and
can only be checked through extensive testing using the producer.
Instead an alternative form, close to C, has been developed for this
purpose. API specifications in this form are transformed by <CODE>tspec</CODE>
into the corresponding <CODE>#pragma token</CODE> statements, while
it applies various internal checks to the API description.   
<P>
Another reason for introducing <CODE>tspec</CODE> is that the <CODE>#pragma
token</CODE> syntax is currently limited in some areas. For example,
at present it has very limited support for expressing constancy of
expressions. By allowing the <CODE>tspec</CODE> syntax to express
this information, the API description will contain all the information
which may be needed in future upgrades to the <CODE>#pragma token</CODE>
syntax. Thus describing an API using <CODE>tspec</CODE> is hopefully
a one off process, whereas describing it directly to the <CODE>#pragma
token</CODE> syntax could require periodic reworkings. Improvements
in the <CODE>#pragma token</CODE> syntax will be reflected in the
translations produced by future versions of <CODE>tspec</CODE>.  
<P>
The <CODE>tspec</CODE> syntax is not designed to be a formal specification
language. Instead it is a pragmatic attempt to capture the common
specification idioms of standard API specifications. A glance at these
specifications shows that they are predominantly C based, but with
an added layer of abstraction - instead of saying that <CODE>t</CODE>
is a specific C type, they say, there exists a type <CODE>t</CODE>,
and so on. The <CODE>tspec</CODE> syntax is designed to reflect this.
<P>
<HR>

<H2><A NAME="Overview">2. Overview of tspec</A></H2>

<H3><A NAME="Levels">2.1. Specification Levels</A></H3>
<P>
Let us begin by examining the various levels of specification with
which <CODE>tspec</CODE> is concerned. At the lowest level it is concerned
with objects - the types, expressions, constants etc. which comprise
the API - and indeed most of this document is concerned with how <CODE>tspec
</CODE> describes these objects. At the highest level, <CODE>tspec</CODE>
is concerned with APIs. We could just describe an API as being a set
of objects, however this is to ignore the internal structure of APIs.
<P>
At the most obvious level the objects in an API are spread over a
number of different system headers. For example, in ANSI, the objects
concerned with file input and output are grouped in <CODE>stdio.h</CODE>,
whereas those concerned with string manipulation are in <CODE>string.h</CODE>.
But a further level of refinement is also required. For example, ANSI
specifies that the type <CODE>size_t</CODE> is defined in both <CODE>stdio.h
</CODE> and <CODE>string.h</CODE>. Therefore <CODE>tspec</CODE> needs
to be able to represent subsets of headers in order to express this
intersection relation.   
<P>
To conclude, <CODE>tspec</CODE> distinguishes four levels of specification
- APIs (which are sets of headers), headers (which are sets of objects),
subsets of headers, and objects. It identifies APIs by an identifying
name chosen by the person performing the API description. The (purely
arbitrary) convention is for short, lower case names, for example:
<UL>
<LI><CODE>ansi</CODE> refers to ANSI C (X3.159),   
<LI><CODE>posix</CODE> refers to POSIX 1003.1,   
<LI><CODE>xpg3</CODE> refers to X/Open Portability Guide 3.   
</UL>
<P>
In this document, headers are identified by the API they belong to
and the header name. Thus <CODE>ansi:stdio.h</CODE> refers to the
<CODE>stdio.h</CODE> header of the ANSI API. Finally subsets of headers
are identified by the header and the subset name. If, for example,
the <CODE>stdio.h</CODE> header of ANSI has a subset named <CODE>file</CODE>,
then this is referred to as <CODE>ansi:stdio.h:file</CODE>.   
<H3><A NAME="Input">2.2. Input Layout</A></H3>
<P>
The <CODE>tspec</CODE> representation of an API is arranged as a directory
with the same name as the API, containing a number of files, one for
each API header. For example, the ANSI API is represented by a directory
<CODE>ansi</CODE> containing files <CODE>ansi/stdio.h</CODE>, <CODE>ansi/string.h
</CODE> etc. In addition each API directory contains a master file
(for ANSI it would be called <CODE>ansi/MASTER</CODE>) which lists
all the headers comprising that API.   
<P>
When <CODE>tspec</CODE> needs to find an API directory it does so
by searching along its input directory path. This is a colon separated
list of directories to be searched. This may be specified in a number
of ways. A default search list is built into <CODE>tspec</CODE>, however
this may be overridden by the system variable <CODE>TSPEC_INPUT</CODE>.
Directories may be added to the start of the path using the <B>-I</B><I>dir</I>
command-line option (see <A HREF="#Options">section 2.5</A> for a
complete list of options). The current working directory is always
added to the start of the path.   
<H3><A NAME="Output">2.3. Output Layout</A></H3>
<P>
<CODE>tspec</CODE> actually outputs two sets of output files, the
include output files, containing the <CODE>#pragma token</CODE> directives
corresponding to the input API, and the source output files, which
provide a rig for TDF library building (see <A HREF="#Libraries">section
6.4</A>). These output files and directories are built up under two
standard output directories - the include output directory, <I>incl_dir</I>
say, and the source output directory, <I>src_dir</I> say. <CODE>tspec</CODE>
has default values for these directories built in, but these may be
overridden in a number of ways. Firstly, if the system variable <CODE>TSPEC_OUTPUT
</CODE> is defined to be <I>dir</I>, say, then <I>incl_dir</I> is
<I>dir</I><CODE>/include</CODE> and <I>src_dir</I> is <I>dir</I><CODE>/src
</CODE>. Secondly, <I>incl_dir</I> and <I>src_dir</I> can be set independently
using the system variables <CODE>TSPEC_INCL_OUTPUT</CODE> and <CODE>TSPEC_SRC_OUTPUT
</CODE> respectively. Finally, they may also be set using the <B>-O</B><I>dir
</I> and <B>-S</B><I>dir</I> command-line options respectively.  
<P>
As an example of the mapping from input files to output files, the
header <CODE>ansi:stdio.h</CODE> is mapped to the include output file
<I>incl_dir</I><CODE>/ansi.api/stdio.h</CODE> and the source output
file <I>src_dir</I><CODE>/ansi.api/stdio.c</CODE>. The header subset
<CODE>ansi:stdio.h:file</CODE> is mapped to its own pair of output
files, <I>incl_dir</I><CODE>/shared/ansi.api/file.h</CODE> and <I>src_dir</I>
<CODE>/ansi.api/file.c</CODE>.   
<P>
The default output file names can be overridden by means of the <CODE>INCLNAME
</CODE> and <CODE>SOURCENAME</CODE> file properties described in 
<A HREF="#Properties">section 5.4</A>.   
<P>
By default, <CODE>tspec</CODE> only creates an output file if the
date stamps on all the input files it depends on indicate that it
needs updating. In effect, <CODE>tspec</CODE> creates an internal
makefile from the dependencies it deduces. This behaviour can be overridden
by means of the <B>-f</B> command-line option, which forces all output
files to be created.   
<P>
In addition, <CODE>tspec</CODE> only creates the source output file
if it is needed for TDF library building. If the corresponding include
output file does not contain any token specifications then the source
output file is suppressed (see <A HREF="#Libraries">section 6.4</A>).

<H3><A NAME="Copyright">2.4. Copyright Messages</A></H3>
<P>
<CODE>tspec</CODE> will optionally add a copyright message to the
start of each include output file. This message is copied from a file
which may be specified either using the <CODE>TSPEC_COPYRIGHT</CODE>
system variable, or by the <B>-C</B><I>file</I> command-line option.

<H3><A NAME="Options">2.5. Command-line Options</A></H3>
<P>
There are three main forms for invoking <CODE>tspec</CODE> on the
command-line, depending on whether it is desired to process an entire
API, a single header from that API, or only a subset of that header.
These are given respectively as:   
<PRE>
        tspec [options] api
        tspec [options] api header
        tspec [options] api header subset
</PRE>
<P>
The valid options include:   
<UL>
<LI>The option <B>-C</B><I>file</I> specifies the copyright message
file (see <A HREF="#Copyright">section 2.4</A>).   
<LI>The option <B>-I</B><I>dir</I> adds a directory to the input directory
search path (see <A HREF="#Input">section 2.2</A>).   
<LI>The option <B>-O</B><I>dir</I> specifies the include output directory
(see <A HREF="#Output">section 2.3</A>).   
<LI>The option <B>-S</B><I>dir</I> specifies the source output directory
(see <A HREF="#Output">section 2.3</A>).   
<LI>The <B>-c</B> option causes <CODE>tspec</CODE> to only check the
input files and not to generate any output files.   
<LI>The <B>-e</B> option causes <CODE>tspec</CODE> only to run its
preprocessor phase, writing the result to the standard output.   
<LI>The <B>-f</B> option forces <CODE>tspec</CODE> to create all output
files regardless of date stamps.   
<LI>The <B>-i</B> option causes <CODE>tspec</CODE> to print an index
of all the objects in the input files (see <A HREF="#Index">section
6.3</A>).  
<LI>The <B>-p</B> option indicates to <CODE>tspec</CODE> that its
input has already been preprocessed (i.e. it is the output of a previous
<B>-e</B> option).   
<LI>The <B>-r</B> option causes <CODE>tspec</CODE> to only produce
output for implemented objects, and not used objects (see <A HREF="#Impl">section
3.2</A>).   
<LI>The <B>-s</B> option causes <CODE>tspec</CODE> to check all the
headers in an API separately rather than, as with the <B>-c</B> option,
all at once.   
<LI>The <B>-u</B> option causes <CODE>tspec</CODE> to generate unique
token names for the specified objects (see <A HREF="#Names">section
4.1.1</A>).  
<LI>The <B>-v</B> option causes <CODE>tspec</CODE> to enter verbose
mode, in which it reports on the output files it creates. If two <B>-v</B>
options are given then <CODE>tspec</CODE> enters very verbose mode,
in which it gives more information on its activities.   
<LI>The <B>-V</B> option causes <CODE>tspec</CODE> to print its current
version number (this document refers to version 2.0).   
</UL>
<P>
In addition <CODE>tspec</CODE> has a local input mode for translating
single headers which are not part of an API into the corresponding
<CODE>#pragma token</CODE> statements. The form:   
<PRE>
        tspec [options] -l file
</PRE>
processes the input file <CODE>file</CODE>, writing the include output
file to the standard output.   
<P>
<HR>

<H2><A NAME="Structure">3. Specifying API Structure</A></H2>
<P>
The basic form of the <CODE>tspec</CODE> description of an API has
already been explained in <A HREF="#Input">section 2.2</A> - it is
a directory containing a set of files corresponding to the headers
in that API. Each file basically consists of a list of the objects
declared in that header. Each object specification is part of a <CODE>tspec
</CODE>
construct. These constructs are identified by keywords. These keywords
always begin with <CODE>+</CODE> to avoid conflict with C identifiers.
Comments may be inserted at any point. These are prefixed by <CODE>#</CODE>
and run to the end of the line.   
<P>
In addition to the basic object specification constructs, <CODE>tspec</CODE>
also has constructs for imposing structure on the API description.
It is these constructs that we consider first.   
<H3><A NAME="Subset">3.1. +SUBSET</A></H3>
<P>
A list of <CODE>tspec</CODE> constructs within a header can be grouped
into a named subset by enclosing them within:   
<PRE>
        +SUBSET &quot;name&quot; := {
            ....
        } ;
</PRE>
where <CODE>name</CODE> is the subset name. These named subsets can
be nested, but are still regarded as subsets of the parent header.
<P>
Subsets are intended to give a layer of resolution beyond that of
the entire header (see <A HREF="#Levels">section 2.1</A>). Each subset
is mapped onto a separate pair of output files, so unwary use of subsets
is discouraged.   
<H3><A NAME="Impl">3.2. +IMPLEMENT and +USE</A></H3>
<P>
<CODE>tspec</CODE> has two import constructs which allow one API,
or header, or subset of a header to be included in another. The first
construct is used to indicate that the given set of objects is also
declared in the including header, and takes one of the forms:   
<PRE>
        +IMPLEMENT &quot;api&quot; ;
        +IMPLEMENT &quot;api&quot;, &quot;header&quot; ;
        +IMPLEMENT &quot;api&quot;, &quot;header&quot;, &quot;subset&quot; ;
</PRE>
The second construct is used to indicate that the objects are only
used in the including header, and take one of the forms:   
<PRE>
        +USE &quot;api&quot; ;
        +USE &quot;api&quot;, &quot;header&quot; ;
        +USE &quot;api&quot;, &quot;header&quot;, &quot;subset&quot; ;
</PRE>
For example, <CODE>posix:stdio.h</CODE> is an extension of <CODE>ansi:stdio.h
</CODE>, so, rather than duplicate all the object specifications from
the latter in the former, it is easier and clearer to use the construct:
<PRE>
        +IMPLEMENT &quot;ansi&quot;, &quot;stdio.h&quot; ;
</PRE>
and just add the extra objects specified by POSIX. Note that this
makes the relationship between the APIs <CODE>ansi</CODE> and <CODE>posix</CODE>
absolutely explicit. <CODE>tspec</CODE> is as much concerned with
the relationships between APIs as their actual contents.   
<P>
Objects which are specified as being declared in more than one header
of an API should also be treated using <CODE>+IMPLEMENT</CODE>. For
example, the type <CODE>size_t</CODE> is declared in a number of <CODE>ansi
</CODE> headers, namely <CODE>stddef.h</CODE>, <CODE>stdio.h</CODE>,
<CODE>string.h</CODE> and <CODE>time.h</CODE>. This can be handled
by declaring <CODE>size_t</CODE> as part of a named subset of, say,
<CODE>ansi:stddef.h</CODE>:   
<PRE>
        +SUBSET &quot;size_t&quot; := {
            +TYPE (unsigned) size_t ;
        } ;
</PRE>
and including this in each of the other headers:   
<PRE>
        +IMPLEMENT &quot;ansi&quot;, &quot;stddef.h&quot;, &quot;size_t&quot; ;
</PRE>
<P>
Another use of <CODE>+IMPLEMENT</CODE> is in the <CODE>MASTER</CODE>
file used to list the headers in an API (see <A HREF="#Input">section
2.2</A>). This basically consists of a list of <CODE>+IMPLEMENT</CODE>
commands, one per header. For example, with <CODE>ansi</CODE> it consists
of:  
<PRE>
        +IMPLEMENT &quot;ansi&quot;, &quot;assert.h&quot; ;
        +IMPLEMENT &quot;ansi&quot;, &quot;ctype.h&quot; ;
        ....
        +IMPLEMENT &quot;ansi&quot;, &quot;time.h&quot; ;
</PRE>
<P>
To illustrate <CODE>+USE</CODE>, <CODE>posix:sys/stat.h</CODE> uses
some types from <CODE>posix:sys/types.h</CODE> but does not define
them. To avoid the user having to include both headers it makes sense
for the description to include the latter in the former (provided
there are no namespace restrictions imposed by the API). This would
be done using the construct:   
<PRE>
        +USE &quot;posix&quot;, &quot;sys/types.h&quot; ;
</PRE>
<P>
On the command-line <CODE>tspec</CODE> is given one set of objects,
be it an API, a header, or a subset of a header. This causes it to
read that set, which may contain <CODE>+IMPLEMENT</CODE> or <CODE>+USE</CODE>
commands. It then reads the sets indicated by these commands, which
again may contain <CODE>+IMPLEMENT</CODE> or <CODE>+USE</CODE> commands,
and so on. It is possible for this process to lead to infinite cycles,
but in this case <CODE>tspec</CODE> raises an error and aborts. In
the legal case, the collection of sets read by <CODE>tspec</CODE>
is the closure of the set given on the command-line under <CODE>+IMPLEMENT
</CODE> and <CODE>+USE</CODE>. Some of these sets will be implemented
- that it to say, connected to the top level by a chain of <CODE>+IMPLEMENT
</CODE> commands - others will merely be used. By default <CODE>tspec</CODE>
produces output for all these sets, but specifying the <B>-r</B> command-line
option restricts it to the implemented sets.   
<P>
For further information on the <CODE>+IMPLEMENT</CODE> and <CODE>+USE</CODE>
commands see <A HREF="#FineImpl">section 6.1</A>.   
<P>
<HR>

<H2><A NAME="Objects">4. Specifying Objects</A></H2>
<P>
The main body of any <CODE>tspec</CODE> description of an API consists
of a list of object specifications. Most of this section is concerned
with the various <CODE>tspec</CODE> constructs for specifying objects
of various kinds, however we start with a few remarks on object names.

<H3><A NAME="S41">4.1. Object Names</A></H3>
<H4><A NAME="Names">4.1.1. Internal and External Names</A></H4>
<P>
All objects specified using <CODE>tspec</CODE> actually have two names.
The first is the internal name by which it is identified within the
program, the second is the external name by which the TDF construct
(actually a token) representing this object is referred to for the
purposes of TDF linking. The internal names are normal C identifiers
and obey the normal C namespace rules (indeed one of the roles of
<CODE>tspec</CODE> is to keep track of these namespaces). The external
token name is constructed by <CODE>tspec</CODE> from the internal
name.   
<P>
<CODE>tspec</CODE> has two strategies for making up these token names.
The first, which is default, is to use the internal name as the external
name (there is an exception to this simple rule, namely field selectors
- see <A HREF="#Field">section 4.9</A>). The second, which is preferred
for standard APIs, is to construct a &quot;unique name&quot; from
the API name, the header and the internal name. For example, under
the first strategy, the external name of the type <CODE>FILE</CODE>
specified in <CODE>ansi:stdio.h</CODE> would be <CODE>FILE</CODE>,
whereas under the second it would be <CODE>ansi.stdio.FILE</CODE>.
The unique name strategy may be specified by passing the <B>-u</B>
command-line option to <CODE>tspec</CODE> (see <A HREF="#Options">section
2.5</A>) or by setting the <CODE>UNIQUE</CODE> property to 1 (see
<A HREF="#Properties">section 5.4</A>).   
<P>
Both strategies involve flattening the several C namespaces into the
single TDF token namespace, which can lead to clashes. For example,
in <CODE>posix:sys/stat.h</CODE> both a structure, <CODE>struct stat</CODE>,
and a procedure, <CODE>stat</CODE>, are specified. In C the two uses
of <CODE>stat</CODE> are in different namespaces and so present no
difficulty, however they are mapped onto the same name in the TDF
token namespace. To work round such difficulties, <CODE>tspec</CODE>
allows an alternative external form to be specified. When the object
is specified the form:   
<PRE>
        iname | ename
</PRE>
may be used to specify the internal name <CODE>iname</CODE> and the
external name <CODE>ename</CODE>.   
<P>
For example, in the <CODE>stat</CODE> case above we could distinguish
between the two uses as follows:   
<PRE>
        +TYPE struct stat | struct_stat ;
        +FUNC int stat ( const char *, struct stat * ) ;
</PRE>
With simple token names the token corresponding to the structure would
be called <CODE>struct_stat</CODE>, whereas that corresponding to
the procedure would still be <CODE>stat</CODE>. With unique token
names the names would be <CODE>posix.stat.struct_stat</CODE> and <CODE>posix.stat.stat
</CODE> respectively.   
<P>
Very occasionally it may be necessary to precisely specify an external
token name. This can be done using the form:   
<PRE>
        iname | &quot;ename&quot;
</PRE>
which makes the object <CODE>iname</CODE> have external name <CODE>ename</CODE>
regardless of the naming strategy used.   
<H4><A NAME="Identifiers">4.1.2. More on Object Names</A></H4>
<P>
Basically the legal identifiers in <CODE>tspec</CODE> (for both internal
and external names) are the same as those in C - strings of upper
and lower case letters, decimal digits or underscores, which do not
begin with a decimal digit. However there is a second class of local
identifiers - those consisting of a tilde followed by any number of
letters, digits or underscores - which are intended to indicate objects
which are local to the API description and should not be visible to
any application using the API. For example, to express the specification
that <CODE>t</CODE> is a pointer type, we could say that there is
a locally named type to which <CODE>t</CODE> is a pointer:   
<PRE>
        +TYPE ~t ;
        +TYPEDEF ~t *t ;
</PRE>
<P>
Finally it is possible to cheat the <CODE>tspec</CODE> namespaces.
It may actually be legal to have two objects of the same name in an
API - they may lie in different branches of a conditional compilation,
or not be allowed to coexist. To allow for this, <CODE>tspec</CODE>
allows version numbers, consisting of a decimal pointer plus a number
of digits, to be appended to an identifier name when it is first introduced.
These version numbers are purely to tell <CODE>tspec</CODE> that this
version of the object is different from a previous version with a
different version number (or indeed without any version number). If
more than one version of an object is specified then which version
is retrieved by <CODE>tspec</CODE> in any look-up operation is undefined.

<H3><A NAME="Func">4.2. +FUNC</A></H3>
<P>
The simplest form of object to specify is a procedure. This is done
by means of:   
<PRE>
        +FUNC prototype ;
</PRE>
where <CODE>prototype</CODE> is the full C prototype of the procedure
being declared. For example, <CODE>ansi:string.h</CODE> contains:
<PRE>
        +FUNC char *strcpy ( char *, const char * ) ;
        +FUNC int strcmp ( const char *, const char * ) ;
        +FUNC size_t strlen ( const char * ) ;
</PRE>
<P>
Strictly speaking, <CODE>+FUNC</CODE> means that the procedure may
be implemented by a macro, but that there is an underlying library
function with the same effect. The exception is for procedures which
take a variable number of arguments, such as:   
<PRE>
        +FUNC int fprintf ( FILE *, const char *, ... ) ;
</PRE>
which cannot be implemented by macros. Occasionally it may be necessary
to specify that a procedure is only a library function, and cannot
be implemented by a macro. In this case the form:   
<PRE>
        +FUNC (extern) prototype ;
</PRE>
should be used. Thus:   
<PRE>
        +FUNC (extern) char *strcpy ( char *, const char * ) ;
</PRE>
would mean that <CODE>strcpy</CODE> was only a library function and
not a macro.   
<P>
Increasingly standard APIs are using prototypes to express their procedures.
However it still may be necessary on occasion to specify procedures
declared using old style declarations. In most cases these can be
easily transcribed into prototype declarations, however things are
not always that simple. For example, <CODE>xpg3:stdlib.h</CODE> declares
<CODE>malloc</CODE> by the old style declaration:   
<PRE>
        void *malloc ( sz )
        size_t sz ;
</PRE>
which is in general different from the prototype:   
<PRE>
        void *malloc ( size_t ) ;
</PRE>
In the first case the argument is passed as the integral promotion
of <CODE>size_t</CODE>, whereas in the second it is passed as a <CODE>size_t
</CODE>. In general we only know that <CODE>size_t</CODE> is an unsigned
integral type, so we cannot assert that it is its own integral promotion.
One possible solution would be to use the C to TDF producer's weak
prototypes (see reference 3). The form:   
<PRE>
        +FUNC (weak) void *malloc ( size_t ) ;
</PRE>
means that <CODE>malloc</CODE> is a library function returning <CODE>void
*</CODE> which is declared using an old style declaration with a single
argument of type <CODE>size_t</CODE>. (For an alternative approach
see <A HREF="#Typedef">section 4.8</A>.)   
<H3><A NAME="Exp">4.3. +EXP and +CONST</A></H3>
<P>
Expressions correspond to constants, identities and variables. They
are specified by:   
<PRE>
        +EXP type exp1, ..., expn ;
</PRE>
where <CODE>type</CODE> is the base type of the expressions <CODE>expi</CODE>
as in a normal C declaration list. For example, in <CODE>ansi:stdio.h</CODE>:
<PRE>
        +EXP FILE *stdin, *stdout, *stderr ;
</PRE>
specifies three expressions of type <CODE>FILE *</CODE>.   
<P>
By default all expressions are rvalues, that is, values which cannot
be assigned to. If an lvalue (assignable) expression is required its
type should be qualified using the keyword <CODE>lvalue</CODE>. This
is an extension to the C type syntax which is used in a similar fashion
to <CODE>const</CODE>. For example, <CODE>ansi:errno.h</CODE> says
that <CODE>errno</CODE> is an assignable lvalue of type <CODE>int</CODE>.
This is expressed as follows:   
<PRE>
        +EXP lvalue int errno ;
</PRE>
On the other hand, <CODE>posix:errno.h</CODE> states that <CODE>errno</CODE>
is an external value of type <CODE>int</CODE>. As with procedures
the <CODE>(extern)</CODE> qualifier may be used to express this as:
<PRE>
        +EXP (extern) int errno ;
</PRE>
Note that this automatically means that <CODE>errno</CODE> is an lvalue,
so the <CODE>lvalue</CODE> qualifier is optional in this case.   
<P>
If all the expressions are guaranteed to be literal constants then
one of the equivalent forms:   
<PRE>
        +EXP (const) type exp1, ..., expn ;
        +CONST type exp1, ..., expn ;
</PRE>
should be used. For example, in <CODE>ansi:errno.h</CODE> we have:
<PRE>
        +CONST int EDOM, ERANGE ;
</PRE>
<P>

<H3><A NAME="Macro">4.4. +MACRO</A></H3>
<P>
The <CODE>+MACRO</CODE> construct is similar in form to the <CODE>+FUNC</CODE>
construct, except that it means that only a macro exists, and no underlying
library function. For example, in <CODE>xpg3:ctype.h</CODE> we have:
<PRE>
        +MACRO int _toupper ( int ) ;
        +MACRO int _tolower ( int ) ;
</PRE>
since these are explicitly stated to be macros and not functions.
Of course the <CODE>(extern)</CODE> qualifier cannot be used with
<CODE>+MACRO</CODE>.   
<P>
One thing which macros can do which functions cannot is to return
assignable values or to assign to their arguments. Thus it is legitimate
for <CODE>+MACRO</CODE> constructs to have their return type or argument
types qualified by <CODE>lvalue</CODE>, whereas this is not allowed
for <CODE>+FUNC</CODE> constructs. For example, in <CODE>svid3:curses.h</CODE>,
a macro <CODE>getyx</CODE> is specified which takes a pointer to a
window and two integer variables and assigns the cursor position of
the window to those variables. This may be expressed by:   
<PRE>
        +MACRO void getyx ( WINDOW *win, lvalue int y, lvalue int x ) ;
</PRE>
<P>

<H3><A NAME="Statement">4.5. +STATEMENT</A></H3>
<P>
The <CODE>+STATEMENT</CODE> construct is very similar to the <CODE>+MACRO</CODE>
construct except that, instead of being a C expression, it is a C
statement (i.e. something ending in a semicolon). As such it does
not have a return type and so takes one of the forms:   
<PRE>
        +STATEMENT stmt ;
        +STATEMENT stmt ( arg1, ..., argn ) ;
</PRE>
depending on whether or not it takes any arguments. (A <CODE>+MACRO</CODE>
without any arguments is an <CODE>+EXP</CODE>, so the no argument
form does not exist for <CODE>+MACRO</CODE>.) As with <CODE>+MACRO</CODE>,
the argument types <CODE>argi</CODE> can be qualified using <CODE>lvalue</CODE>.

<H3><A NAME="Define">4.6. +DEFINE</A></H3>
<P>
It is possible to insert macro definitions directly into <CODE>tspec</CODE>
using the <CODE>+DEFINE</CODE> construct. This has two forms depending
on whether the macro has arguments:   
<PRE>
        +DEFINE name %% text %% ;
        +DEFINE name ( arg1, ..., argn ) %% text %% ;
</PRE>
These translate directly into:   
<PRE>
        #define name text
        #define name( arg1, ..., argn ) text
</PRE>
<P>
The macro definition, <CODE>text</CODE>, consists of any string of
characters delimited by double percents. If <CODE>text</CODE> is a
simple number or a single identifier then the double percents may
be omitted. Thus in <CODE>ansi:stddef.h</CODE> we have:   
<PRE>
        +DEFINE NULL 0 ;
</PRE>
<P>

<H3><A NAME="Type">4.7. +TYPE</A></H3>
<P>
New types may be specified using the <CODE>+TYPE</CODE> construct.
This has the form:   
<PRE>
        +TYPE type1, ..., typen ;
</PRE>
where each <CODE>typei</CODE> has one of the forms:   
<UL>
<LI><CODE>name</CODE> for a general type (about which we know nothing
more),   
<LI><CODE>(struct) name</CODE> for a structure type,   
<LI><CODE>(union) name</CODE> for a union type,   
<LI><CODE>struct name</CODE> for a structure tag,   
<LI><CODE>union name</CODE> for a union tag,   
<LI><CODE>(int) name</CODE> for an integral type,   
<LI><CODE>(signed) name</CODE> for a signed integral type,   
<LI><CODE>(unsigned) name</CODE> for an unsigned integral type,  
<LI><CODE>(float) name</CODE> for a floating type,   
<LI><CODE>(arith) name</CODE> for an arithmetic (integral or floating)
type,  
<LI><CODE>(scalar) name</CODE> for a scalar (arithmetic or pointer)
type.   
</UL>
<P>
To make clear the distinction between structure types and structure
tags, if we have in C:   
<PRE>
        typedef struct tag { int x, y ; } type ;
</PRE>
then <CODE>type</CODE> is a structure type and <CODE>tag</CODE> is
a structure tag.   
<P>
For example, in <CODE>ansi</CODE> we have:   
<PRE>
        +TYPE FILE ;
        +TYPE struct lconv ;
        +TYPE (struct) div_t ;
        +TYPE (signed) ptrdiff_t ;
        +TYPE (unsigned) size_t ;
        +TYPE (arith) time_t ;
        +TYPE (int) wchar_t ;
</PRE>

<H3><A NAME="Typedef">4.8. +TYPEDEF</A></H3>
<P>
It is also possible to define new types in terms of existing types.
This is done using the <CODE>+TYPEDEF</CODE> construct, which is identical
in form to the C <CODE>typedef</CODE> construct. This construct can
be used to define pointer, procedure and array types, but not compound
structure and union types. For these see <A HREF="#Field">section
4.9</A>
below.   
<P>
For example, in <CODE>xpg3:search.h</CODE> we have:   
<PRE>
        +TYPE struct entry ;
        +TYPEDEF struct entry ENTRY ;
</PRE>
<P>
There are a couple of special forms. To understand the first, note
that C uses <CODE>void</CODE> function returns for two purposes. Firstly
to indicate that the function does not return a value, and secondly
to indicate that the function does not return at all (<CODE>exit</CODE>
is an example of this second usage). In TDF terms, in the first case
the function returns <CODE>TOP</CODE>, in the second it returns <CODE>BOTTOM
</CODE>. <CODE>tspec</CODE> allows types to be introduced which have
the second meaning. For example, we could have:   
<PRE>
        +TYPEDEF ~special ( &quot;bottom&quot; ) ~bottom ;
        +FUNC ~bottom exit ( int ) ;
</PRE>
meaning that the local type <CODE>~bottom</CODE> is the <CODE>BOTTOM</CODE>
form of <CODE>void</CODE>. The procedure <CODE>exit</CODE>, which
never returns, can then be declared to return <CODE>~bottom</CODE>
rather than <CODE>void</CODE>. Other such special types may be added
in future.   
<P>
The second special form:   
<PRE>
        +TYPEDEF ~promote ( x ) y ;
</PRE>
means that <CODE>y</CODE> is an integral type which is the integral
promotion of <CODE>x</CODE>. <CODE>x</CODE> must have previously been
declared as an integral type. This gives an alternative approach to
the old style procedure declaration problem described in  
<A HREF="#Func">section 4.2</A>. Recall that:   
<PRE>
        void *malloc ( sz )
        size_t sz ;
</PRE>
means that <CODE>malloc</CODE> has one argument which is passed as
the integral promotion of <CODE>size_t</CODE>. This could be expressed
as follows:   
<PRE>
        +TYPEDEF ~promote ( size_t ) ~size_t ;
        +FUNC void *malloc ( ~size_t ) ;
</PRE>
introducing a local type to stand for the integral promotion of <CODE>size_t
</CODE>.   
<H3><A NAME="Field">4.9. +FIELD</A></H3>
<P>
Having specified a structure or union type, or a structure or union
tag, we may wish to specify certain fields of this structure or union.
This is done using the <CODE>+FIELD</CODE> construct. This takes the
form:   
<PRE>
        +FIELD type {
            ftype field1, ..., fieldn ;
            ....
        } ;
</PRE>
where <CODE>type</CODE> is the structure or union type and <CODE>field1</CODE>,
..., <CODE>fieldn</CODE> are field selectors derived from the base
type <CODE>ftype</CODE> as in a normal C structure definition. <CODE>type</CODE>
may have one of the forms:   
<UL>
<LI><CODE>(struct) name</CODE> for a structure type,   
<LI><CODE>(union) name</CODE> for a union type,   
<LI><CODE>struct name</CODE> for a structure tag,   
<LI><CODE>union name</CODE> for a union tag,   
<LI><CODE>name</CODE> for a previously declared structure or union
type.   
</UL>
<P>
Except in the final case (where it is not clear if <CODE>type</CODE>
is a structure or a union), it is not necessary to have previously
introduced <CODE>type</CODE> using a <CODE>+TYPE</CODE> construct
- this declaration is implicit in the <CODE>+FIELD</CODE> construct.
<P>
For example, in <CODE>ansi:time.h</CODE> we have:   
<PRE>
        +FIELD struct tm {
            int tm_sec ;
            int tm_min ;
            int tm_hour ;
            int tm_mday ;
            int tm_mon ;
            int tm_year ;
            int tm_wday ;
            int tm_yday ;
            int tm_isdst ;
        } ;
</PRE>
meaning that there exists a structure with tag <CODE>tm</CODE> with
various fields of type <CODE>int</CODE>. Any implementation must have
these corresponding fields, but they need not be in the given order,
nor do they have to comprise the whole structure.   
<P>
As was mentioned above (in <A HREF="#Names">4.1.1</A>), field selectors
form a special case when <CODE>tspec</CODE> is making up external
token names. For example, in the case above, the token name for the
<CODE>tm_sec</CODE> field is either <CODE>tm.tm_sec</CODE> or <CODE>ansi.time.tm.tm_sec
</CODE>, depending on whether or not unique token names are used.
<P>
It is possible to have several <CODE>+FIELD</CODE> constructs referring
to the same structure or union. For example, <CODE>posix:dirent.h</CODE>
declares a structure with tag <CODE>dirent</CODE> and one field, <CODE>d_name
</CODE>, of this structure. <CODE>xpg3:dirent.h</CODE> extends this
by adding another field, <CODE>d_ino</CODE>.   
<P>
There is a second form of the <CODE>+FIELD</CODE> construct which
has more in common with the <CODE>+TYPEDEF</CODE> construct. The form:
<PRE>
        +FIELD type := {
            ftype field1, ..., fieldn ;
            ....
        } ;
</PRE>
means that the type <CODE>type</CODE> is defined to be exactly the
given structure or union type, with precisely the given fields in
the given order.   
<H3><A NAME="Nat">4.10. +NAT</A></H3>
<P>
In the example given in <A HREF="#Field">section 4.9</A>, <CODE>posix:dirent.h
</CODE>
specifies that the <CODE>d_name</CODE> field of <CODE>struct dirent</CODE>
is a fixed sized array of characters, but that the size of this array
is implementation dependent. We therefore have to introduce a value
to stand for the size of this array using the <CODE>+NAT</CODE> construct.
This has the form:   
<PRE>
        +NAT nat1, ..., natn ;
</PRE>
where <CODE>nat1</CODE>, ..., <CODE>natn</CODE> are the array sizes
to be declared. The example thus becomes:   
<PRE>
        +NAT ~dirent_d_name_size ;
        +FIELD struct dirent {
            char d_name [ ~dirent_d_name_size ] ;
        } ;
</PRE>
Note the use of a local variable to stand for a value, namely the
array size, which is invisible to the user (see  
<A HREF="#Identifiers">section 4.1.2</A>).  
<P>
As another example, in <CODE>ansi:setjmp.h</CODE> we know that <CODE>jmp_buf
</CODE> is an array type. We therefore introduce objects to stand
for the type which it is an array of and for the size of the array,
and define <CODE>jmp_buf</CODE> by a <CODE>+TYPEDEF</CODE> command:
<PRE>
        +NAT ~jmp_buf_size ;
        +TYPE ~jmp_buf_elt ;
        +TYPEDEF ~jmp_buf_elt jmp_buf [ ~jmp_buf_size ] ;
</PRE>
Again, local variables have been used for the introduced objects.

<H3><A NAME="Enum">4.11. +ENUM</A></H3>
<P>
Currently <CODE>tspec</CODE> only has limited support for enumeration
types. A <CODE>+ENUM</CODE> construct is translated directly into
a C definition of an enumeration type. The <CODE>+ENUM</CODE> construct
has the form:   
<PRE>
        +ENUM etype := {
            entry,
            ....
        } ;
</PRE>
where <CODE>etype</CODE> is the enumeration type being defined - either
a type name or <CODE>enum etag</CODE> for some enumeration tag <CODE>etag</CODE>
- and each <CODE>entry</CODE> has one of the forms:   
<PRE>
        name
        name = number
</PRE>
as in a C enumeration type. For example, in <CODE>xpg3:search.h</CODE>
we have:   
<PRE>
        +ENUM ACTION := { FIND, ENTER } ;
</PRE>

<H3><A NAME="Token">4.12. +TOKEN</A></H3>
<P>
As was mentioned in <A HREF="#Intro">section 1</A>, the <CODE>#pragma
token</CODE> syntax is highly complex, and the token descriptions
output by <CODE>tspec</CODE> form only a small subset of those possible.
It is possible to directly access the full <CODE>#pragma token</CODE>
syntax from <CODE>tspec</CODE> using the construct:   
<PRE>
        +TOKEN name %% text %% ;
</PRE>
where the token <CODE>name</CODE> is defined by the sequence of characters
<CODE>text</CODE>, which is delimited by double percents. This is
turned into the token description:   
<PRE>
        #pragma token text name #
</PRE>
<P>
No checks are applied to <CODE>text</CODE>. A more sophisticated mechanism
for defining complex tokens may be introduced in a later version of
<CODE>tspec</CODE>.   
<P>
For example, in <CODE>ansi:stdarg.h</CODE> a token <CODE>va_arg</CODE>
is defined which takes a variable of type <CODE>va_list</CODE> and
a type <CODE>t</CODE> and returns a value of type <CODE>t</CODE>.
This is given by:   
<PRE>
        +TOKEN va_arg %% PROC ( EXP lvalue : va_list : e, TYPE t ) EXP rvalue : t : %% ;
</PRE>
See reference 3 for more details on the token syntax.   
<P>
<HR>

<H2><A NAME="Others">5. Other tspec Constructs</A></H2>
<P>
Although most <CODE>tspec</CODE> constructs are concerned either with
specifying new objects or imposing structure upon various sets of
objects, there are a few which do not fall into these categories.

<H3><A NAME="If">5.1. +IF, +ELSE and +ENDIF</A></H3>
<P>
It is possible to introduce conditional compilation into the API description
by means of the constructs:   
<PRE>
        +IF %% text %%
        +IFDEF %% text %%
        +IFNDEF %% text %%
        +ELSE
        +ENDIF
</PRE>
which are translated into:   
<PRE>
        #if text
        #ifdef text
        #ifndef text
        #else /* text */
        #endif /* text */
</PRE>
respectively. If <CODE>text</CODE> is just a simple number or a single
identifier the double percent delimiters may be excluded.   
<P>
A couple of special <CODE>+IFDEF</CODE> (and also <CODE>+IFNDEF</CODE>)
forms are available which are useful on occasion. These are:   
<PRE>
        +IFDEF ~building_libs
        +IFDEF ~protect ( &quot;api&quot;, &quot;header&quot; )
</PRE>
The macros in these constructs expand respectively to <CODE>__BUILDING_LIBS
</CODE> which, by convention is defined if and only if TDF library
building is taking place (see <A HREF="#Libraries">section 6.4</A>),
and the protection macro <CODE>tspec</CODE> makes up to protect the
file  
<CODE>api:header</CODE> against multiple inclusion (see  
<A HREF="#Protect">section 6.2</A>).   
<H3><A NAME="Text">5.2. Quoted Text</A></H3>
<P>
It is sometimes desirable to include text in the specification file
which will be copied directly into one of the output files - for example,
sections of C. This can be done by enclosing the text for copying
into the include output file in double percents:   
<PRE>
        %% text %%
</PRE>
and text for copying into the source output file in triple percents:
<PRE>
        %%% text %%%
</PRE>
<P>
In fact more percents may be used. An even number always indicates
text for the include output file, and an odd number the source output
file. Note that any <CODE>#</CODE> characters in <CODE>text</CODE>
are copied as normal, and not treated as comments. This also applies
to the other cases where percent delimiters are used.   
<H3><A NAME="Comment">5.3. C Comments</A></H3>
<P>
A special case of quoted text are C style comments:   
<PRE>
        /* text */
</PRE>
which are copied directly into the include output file.   
<H3><A NAME="Properties">5.4. File Properties</A></H3>
<P>
Various properties of individual sets of objects or global properties
can be set using file properties. These take the form:   
<PRE>
        $property = number ;
</PRE>
for numeric (or boolean) properties, and:   
<PRE>
        $property = &quot;string&quot; ;
</PRE>
for string properties.   
<P>
The valid property names are as follows:   
<UL>
<LI><CODE>APINAME</CODE> is a string property which may be used to
override the API name of the current set of objects.   
<LI><CODE>FILE</CODE> is a string property which is used by the <CODE>tspec
</CODE> preprocessor to indicate the current input file name.   
<LI><CODE>FILENAME</CODE> is a string property which may be used to
override the header name of the current set of objects.   
<LI><CODE>INCLNAME</CODE> is a string property which may be used to
set the name of the include output file in place of the default name
given in <A HREF="#Output">section 2.3</A>. Setting the property to
the empty string suppresses the output of this file.   
<LI><CODE>INTERFACE</CODE> is a numeric property which may be set
to force the creation of the source output file and cleared to suppress
it.   
<LI><CODE>LINE</CODE> is a numeric property which is used by the <CODE>tspec
</CODE> preprocessor to indicate the current input file line number.
<LI><CODE>METHOD</CODE> is a string property which may be used to
specify alternative construction methods for TDF library building
(see <A HREF="#Libraries">section 6.4</A>).   
<LI><CODE>PREFIX</CODE> is a string property which may be used as
a prefix to unique token names in place of the API and header names
(see <A HREF="#Names">section 4.1.1</A>).   
<LI><CODE>PROTECT</CODE> is a string property which may be used to
set the macro used by <CODE>tspec</CODE> to protect the include output
file against multiple inclusions (see <A HREF="#Protect">section 6.2</A>).
Setting the property to the empty string suppresses this macro.  
<LI><CODE>SOURCENAME</CODE> is a string property which may be used
to set the name of the source output file in place of the default
name given in <A HREF="#Output">section 2.3</A>. Setting the property
to the empty string suppresses the output of this file.   
<LI><CODE>SUBSETNAME</CODE> is a string property which may be used
to override the subset name of the current set of objects.   
<LI><CODE>UNIQUE</CODE> is a numeric property which may be used to
switch the unique token name flag on and off (see <A HREF="#Names">section
4.1.1</A>). For standard APIs it is recommended that this property
is set to 1 in the API <CODE>MASTER</CODE> file.   
<LI><CODE>VERBOSE</CODE> is a numeric property which may be used to
set the level of the verbose option (see <A HREF="#Options">section
2.5</A>).  
<LI><CODE>VERSION</CODE> is a string property which may be used to
assign a version number or other identification to a <CODE>tspec</CODE>
description. This information is reproduced in the corresponding include
output file.   
</UL>
<P>
<HR>

<H2><A NAME="S6">6. Miscellaneous Topics</A></H2>
<P>
In this section we round up a few miscellaneous topics.   
<H3><A NAME="FineImpl">6.1. Fine Control of Included Files</A></H3>
<P>
The <CODE>+IMPLEMENT</CODE> and <CODE>+USE</CODE> commands described
in <A HREF="#Impl">section 3.2</A> 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  
<CODE>tspec</CODE> syntax has been extended to allow for fine control
of the output corresponding to <CODE>+IMPLEMENT</CODE> and <CODE>+USE</CODE>
commands. This takes the forms:   
<PRE>
        +IMPLEMENT &quot;api&quot; (key) ;
        +IMPLEMENT &quot;api&quot;, &quot;header&quot; (key) ;
        +IMPLEMENT &quot;api&quot;, &quot;header&quot;, &quot;subset&quot; (key) ;
</PRE>
with corresponding forms for <CODE>+USE</CODE>. <CODE>key</CODE> specifies
which output files the inclusion commands should appear in. It can
be:   
<UL>
<LI><CODE>??</CODE>, indicating neither output file,   
<LI><CODE>!?</CODE>, indicating the include output file only,   
<LI><CODE>?!</CODE>, indicating the source output file only,   
<LI><CODE>!!</CODE>, indicating both output files (this is the same
as the normal form).   
</UL>
<P>
The second refinement comes from the fact that APIs fall into two
categories - the base APIs, such as <CODE>ansi</CODE>, <CODE>posix</CODE>
and <CODE>xpg3</CODE>, and the extension APIs, such as <CODE>x11</CODE>,
the X Windows API. The latter can be used to extend the former, so
that we can form <CODE>ansi</CODE> plus <CODE>x11</CODE>, <CODE>posix</CODE>
plus <CODE>x11</CODE>, and so on. Base APIs may be distinguished in
<CODE>tspec</CODE> by including the command:   
<PRE>
        +BASE_API ;
</PRE>
in their <CODE>MASTER</CODE> 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 <CODE>+USE
</CODE> command. Instead the special form:   
<PRE>
        +USE ( &quot;api&quot; ), &quot;header&quot; ;
</PRE>
is provided for this purpose (this is the only permitted form). It
indicates that <CODE>tspec</CODE> should use the <CODE>api</CODE>
version of <CODE>header</CODE> for checking purposes, but allow the
inclusion of the version from the base API in normal use.   
<H3><A NAME="Protect">6.2. Protection Macros</A></H3>
<P>
Each include output file is surrounded by a construct of the form:
<PRE>
        #ifndef MACRO
        #define MACRO
        ....
        #endif /* MACRO */
</PRE>
to protect it against multiple inclusions. Normally <CODE>tspec</CODE>
will generate the macro name, <CODE>MACRO</CODE>, but it can be set
using the <CODE>PROTECT</CODE> file property (see  
<A HREF="#Properties">section 5.4</A>). Setting <CODE>PROTECT</CODE>
to the empty string suppresses the protection construct altogether.
(Also see  
<A HREF="#If">section 5.1</A>.)   
<H3><A NAME="Index">6.3. Index Printing</A></H3>
<P>
If it is invoked with the <B>-i</B> command-line option, instead of
creating its output file, <CODE>tspec</CODE> 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.   
<H3><A NAME="Libraries">6.4. TDF Library Building</A></H3>
<P>
As was explained in reference 1, the <CODE>#pragma token</CODE> headers
output by <CODE>tspec</CODE> 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 <CODE>tspec</CODE>.
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). <CODE>tspec</CODE> uses a
standard macro, <CODE>__BUILDING_LIBS</CODE>, to distinguish between
the two cases. It is assumed to be defined if and only if library
building is taking place. <CODE>tspec</CODE> descriptions can access
this macro directly using <CODE>~building_libs</CODE> (see  
<A HREF="#If">section 5.1</A>).   
<P>
The actual library building process consists of compiling the <CODE>#pragma
token</CODE> 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 <CODE>tspec</CODE>
creates the source output files for each implemented header <CODE>api:header
</CODE> containing something like:   
<PRE>
        #pragma implement interface &lt;../api/header&gt;
        #include &lt;header&gt;
</PRE>
together with a makefile to compile all these programs to token definitions
and to combine these token definitions into a token library. In fact
two makefiles are created in the source output directory (see  
<A HREF="#Output">section 2.3</A>). The first is called <CODE>M_api</CODE>
and is designed for stand-alone library construction. The second is
called  
<CODE>Makefile</CODE> and is designed for use with the library building
script <CODE>MAKE_LIBS</CODE> provided with <CODE>tspec</CODE>.  
<P>
There are other methods whereby the source output file may be changed
into a set of token definitions. For example, in <CODE>c:sys.h</CODE>
the <CODE>METHOD</CODE> file property (see <A HREF="#Properties">section
5.4</A>) is set to <CODE>TDP</CODE>, causing the <CODE>tdp</CODE>
program to be invoked to produce the definitions for the basic C tokens
for the system. As another example consider:   
<PRE>
        $METHOD = &quot;TNC&quot; ;
        +MACRO double fl_abs ( double ) ;
        %%%
            ( make_tokdef fl_abs ( exp x ) exp
                ( floating_abs impossible x ) )
        %%%
</PRE>
<P>
The include output file will specify a token <CODE>fl_abs</CODE> which
takes a <CODE>double</CODE> and returns a <CODE>double</CODE>. The
<CODE>TNC</CODE> method tells <CODE>MAKE_LIBS</CODE> that the source
output file, which will just contain the quoted text:   
<PRE>
        ( make_tokdef fl_abs ( exp x ) exp
            ( floating_abs impossible x ) )
</PRE>
is an input file for the TDF notation compiler, <CODE>tnc</CODE> (see
reference 2). Thus we have defined a token which directly accesses
the TDF <CODE>floating_abs</CODE> construct.   
<P>
<HR>

<H2><A NAME="S7">7. Changes in tspec 2.0</A></H2>
<P>
This document describes <CODE>tspec</CODE> version 2.0. <CODE>tspec</CODE>
2.0 contains significant changes from previous releases. For convenience
the main changes which are visible to the <CODE>tspec</CODE> user
are listed here:   
<UL>
<LI>The added specification level of named subsets of headers has
been introduced (see <A HREF="#Levels">section 2.1</A>). This has
been done by introducing the <CODE>+SUBSET</CODE> construct and extending
the  
<CODE>+IMPLEMENT</CODE> and <CODE>+USE</CODE> constructs, as well
as the command-line options. The previous method of dealing with such
subsets - namely shared headers - is now obsolete and its use is discouraged.
<LI>A number of new command-line options have been added, and some
of the existing options have been modified slightly (see  
<A HREF="#Options">section 2.5</A>).   
<LI>The suffix <CODE>.api</CODE> has been added to the output directories
(see <A HREF="#Output">section 2.3</A>) to avoid possible confusion
with other include file directories.   
<LI>The use of identifiers beginning with <CODE>~</CODE> as local
variables is new (see <A HREF="#Identifiers">section 4.1.2</A>). 
<LI>The <CODE>+STATEMENT</CODE> and <CODE>+DEFINE</CODE> constructs
(see <A HREF="#Statement">section 4.5</A> and <A HREF="#Define">section
4.6</A>) are new.   
<LI>The <CODE>(extern)</CODE>, <CODE>(weak)</CODE> and <CODE>(const)</CODE>
qualifiers for <CODE>+FUNC</CODE> and <CODE>+EXP</CODE> (see  
<A HREF="#Func">section 4.2</A> and <A HREF="#Exp">section 4.3</A>)
are new.   
<LI>The <CODE>(signed)</CODE> and <CODE>(unsigned)</CODE> qualifiers
for <CODE>+TYPE</CODE> (see <A HREF="#Type">section 4.7</A>) are new.
<LI>The <CODE>~special</CODE> type constructor (see  
<A HREF="#Typedef">section 4.8</A>) is new.   
<LI>The <CODE>~abstract</CODE> type constructor has been abandoned.
<LI>The <CODE>+BASE_API</CODE> command described in  
<A HREF="#FineImpl">section 6.1</A> is new.   
<LI>The indexing routines (see <A HREF="#Index">section 6.3</A>) have
been greatly improved.   
</UL>
<P>
<HR>

<H2><A NAME="S8">8. References</A></H2>
<P>
<I>&quot;TDF and Portability&quot;</I>, DRA, 1993.   
<P>
<I>&quot;The TDF Notation Compiler&quot;</I>, DRA, 1993.   
<P>
<I>&quot;The C to TDF Producer&quot;</I>, DRA, 1993.   
<P>
<HR>
<P><I>Part of the <A HREF="../index.html">TenDRA Web</A>.<BR>Crown
Copyright &copy; 1998.</I></P>
</BODY>
</HTML>