Subversion Repositories tendra.SVN

Rev

Rev 6 | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?xml version="1.0" standalone="no"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
  "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">

<!--
  $Id$
-->
    
<book>
  <bookinfo>
    <title>tspec - An API Specification Tool</title>

    <corpauthor>The TenDRA Project</corpauthor>

    <author>
      <firstname>Jeroen</firstname>
      <surname>Ruigrok van der Werven</surname>
    </author>
    <authorinitials>JRvdW</authorinitials>
    <pubdate>2004</pubdate>

    <copyright>
      <year>2004</year>
      <year>2005</year>

      <holder>The TenDRA Project</holder>
    </copyright>

    <copyright>
      <year>1998</year>

      <holder>DERA</holder>
    </copyright>
  </bookinfo>
  
  <chapter id="Intro">
    <title>Introduction</title>

      <para>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 "abstract implementation" of
        the API needs to be provided.</para>
    
      <para>But of course, an "abstract implementation" 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.</para>
    
      <para>In this document we address the problem of how to translate a
        standard API specification into its TDF representation, by describing
        a tool, <command>tspec</command>, which has been developed for
        this purpose.</para>
    
      <para>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 <command>tspec</command> into the corresponding
        <code>#pragma token</code> statements, while it applies various
        internal checks to the API description.</para>
    
      <para>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 <command>tspec</command>.</para>
    
      <para>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.</para>
  </chapter>
  
  <chapter id="Overview">
    <title>Overview of tspec</title>
  
      <sect1 id="Levels">
        <title>Specification Levels</title>
    
        <para>Let us begin by examining the various levels of specification
          with which <command>tspec</command> 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 <command>tspec</command>
          describes these objects. At the highest level,
          <command>tspec</command> 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.</para>
      
        <para>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.</para>
      
        <para>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:
      
          <itemizedlist>
            <listitem>
              <para><code>ansi</code> refers to ANSI C (X3.159),</para>
            </listitem>
        
            <listitem>
              <para><code>posix</code> refers to POSIX 1003.1,</para>
            </listitem>
        
            <listitem>
              <para><code>xpg3</code> refers to X/Open Portability Guide
                3.</para>
            </listitem>
          </itemizedlist></para>
      
        <para>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>.</para>
      </sect1>

      <sect1 id="Input">
        <title>Input Layout</title>
  
        <para>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.</para>
      
        <para>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
          <option>-I</option><filename>dir</filename> command-line option (see
          <link linkend="Options">section 2.5</link> for a complete list of
          options). The current working directory is always added to the start
          of the path.</para>
      </sect1>

      <sect1 id="Output">
        <title>Output Layout</title>
  
        <para><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
          <link linkend="Libraries">section 6.4</link>). These output files and
          directories are built up under two standard output directories - the
          include output directory, <filename>incl_dir</filename> say, and the
          source output directory, <filename>src_dir</filename> 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
          <filename>dir</filename>, say, then <filename>incl_dir</filename> is
          <filename>dir/include</filename> and <filename>src_dir</filename> is
          <filename>dir/src</filename>. Secondly,
          <filename>incl_dir</filename> and <filename>src_dir</filename> 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
          <option>-O</option><filename>dir</filename> and
          <option>-S</option><filename>dir</filename> command-line options
          respectively.</para>
      
        <para>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 <filename>incl_dir/ansi.api/stdio.h</filename> and the source
          output file <filename>src_dir/ansi.api/stdio.c</filename>.  The
          header subset <code>ansi:stdio.h:file</code> is mapped to its own
          pair of output files,
          <filename>incl_dir/shared/ansi.api/file.h</filename> and
          <filename>src_dir/ansi.api/file.c</filename>.</para>
      
        <para>The default output file names can be overridden by means of the
          <code>INCLNAME</code> and <code>SOURCENAME</code> file properties
          described in <link linkend="Properties">section 5.4</link>.</para>
      
        <para>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 <option>-f</option> command-line option,
          which forces all output files to be created.</para>
      
        <para>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
          <link linkend="Libraries">section 6.4</link>).</para>
      </sect1>

      <sect1 id="Copyright">
        <title>Copyright Messages</title>
  
        <para><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
          <option>-C</option><filename>file</filename> command-line
          option.</para>
      </sect1>

      <sect1 id="Options">
        <title>Command-line Options</title>
  
        <para>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:

          <programlisting>
tspec [options] api
tspec [options] api header
tspec [options] api header subset
          </programlisting></para>
  
        <para>The valid options include:
          <itemizedlist>
            <listitem>
              <para>The option <option>-C</option><filename>file</filename>
                specifies the copyright message file (see
                <link linkend="Copyright">section 2.4</link>).</para>
            </listitem>
        
            <listitem>
              <para>The option <option>-I</option><filename>dir</filename>
                adds a directory to the input directory search path (see
                <link linkend="Input">section 2.2</link>).</para>
            </listitem>
        
            <listitem>
              <para>The option <option>-O</option><filename>dir</filename>
                specifies the include output directory (see
                <link linkend="Output">section 2.3</link>).</para>
            </listitem>
        
            <listitem>
              <para>The option <option>-S</option><filename>dir</filename>
                specifies the source output directory (see
                <link linkend="Output">section 2.3</link>).</para>
            </listitem>
        
            <listitem>
              <para>The <option>-c</option> option causes <code>tspec</code>
              to only check the input files and not to generate any output
              files.</para>
            </listitem>
        
            <listitem>
              <para>The <option>-e</option> option causes <code>tspec</code>
                only to run its preprocessor phase, writing the result to the
                standard output.</para>
              </listitem>
        
            <listitem>
              <para>The <option>-f</option> option forces <code>tspec</code>
                to create all output files regardless of date
                stamps.</para>
            </listitem>
        
            <listitem>
              <para>The <option>-i</option> option causes <code>tspec</code>
              to print an index of all the objects in the input files (see
              <link linkend= "Index">section 6.3</link>).</para>
            </listitem>
        
            <listitem>
              <para>The <option>-p</option> option indicates to
                <code>tspec</code> that its input has already been
                preprocessed (i.e. it is the output of a previous
                <option>-e</option> option).</para>
            </listitem>
        
            <listitem>
              <para>The <option>-r</option> option causes <code>tspec</code>
              to only produce output for implemented objects, and not used
              objects (see <link linkend="Impl">section 3.2</link>).</para>
            </listitem>
        
            <listitem>
              <para>The <option>-s</option> option causes <code>tspec</code>
              to check all the headers in an API separately rather than, as
              with the <option>-c</option> option, all at once.</para>
            </listitem>
        
            <listitem>
              <para>The <option>-u</option> option causes <code>tspec</code>
              to generate unique token names for the specified objects (see
              <link linkend="Names">section 4.1.1</link>).</para>
            </listitem>
        
            <listitem>
              <para>The <option>-v</option> option causes <code>tspec</code>
              to enter verbose mode, in which it reports on the output files
              it creates. If two <option>-v</option> options are given then
              <code>tspec</code> enters very verbose mode, in which it gives
              more information on its activities.</para>
            </listitem>
        
            <listitem>
              <para>The <option>-V</option> option causes <code>tspec</code>
              to print its current version number (this document refers to
              version 2.0).</para>
            </listitem>
          </itemizedlist></para>
  
        <para>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:

          <programlisting>
tspec [options] -l file
          </programlisting>

          processes the input file <code>file</code>, writing the include
          output file to the standard output.
        </para>
      </sect1>
  </chapter>
  
  <chapter id="Structure">
    <title>Specifying API Structure</title>
  
      <para>The basic form of the <code>tspec</code> description of an API has
        already been explained in <link linkend="Input">section 2.2</link> -
        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.</para>
  
      <para>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.</para>
  
      <sect1 id="Subset">
        <title>+SUBSET</title>
  
        <para>A list of <code>tspec</code> constructs within a header can be
          grouped into a named subset by enclosing them within:

          <programlisting>
+SUBSET "name" := {
    ....
} ;
          </programlisting>

          where <code>name</code> is the subset name. These named subsets can
          be nested, but are still regarded as subsets of the parent
          header.</para>
  
        <para>Subsets are intended to give a layer of resolution beyond that
          of the entire header (see <link linkend="Levels">section
          2.1</link>).  Each subset is mapped onto a separate pair of output
          files, so unwary use of subsets is discouraged.</para>
      </sect1>

      <sect1 id="Impl">
        <title>+IMPLEMENT and +USE</title>
  
        <para><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:

          <programlisting>
+IMPLEMENT "api" ;
+IMPLEMENT "api", "header" ;
+IMPLEMENT "api", "header", "subset" ;
          </programlisting></para>

        <para>The second construct is used to indicate that the objects are
          only used in the including header, and take one of the forms:

          <programlisting>
+USE "api" ;
+USE "api", "header" ;
+USE "api", "header", "subset" ;
          </programlisting></para>

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

          <programlisting>
+IMPLEMENT "ansi", "stdio.h" ;
          </programlisting>

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

          <programlisting>
+SUBSET "size_t" := {
    +TYPE (unsigned) size_t ;
} ;
          </programlisting>

          and including this in each of the other headers:

          <programlisting>
+IMPLEMENT "ansi", "stddef.h", "size_t" ;
          </programlisting></para>
  
        <para>Another use of <code>+IMPLEMENT</code> is in the
          <code>MASTER</code> file used to list the headers in an API (see
          <link linkend="Input">section 2.2</link>). This basically consists
          of a list of <code>+IMPLEMENT</code> commands, one per header. For
          example, with <code>ansi</code> it consists of:

          <programlisting>
+IMPLEMENT "ansi", "assert.h" ;
+IMPLEMENT "ansi", "ctype.h" ;
....
+IMPLEMENT "ansi", "time.h" ;
          </programlisting></para>
  
        <para>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:

          <programlisting>
+USE "posix", "sys/types.h" ;
          </programlisting></para>
  
        <para>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 <option>-r</option> command-line option
          restricts it to the implemented sets.</para>
  
        <para>For further information on the <code>+IMPLEMENT</code> and
          <code>+USE</code> commands see
          <link linkend="FineImpl">section 6.1</link>.</para>
      </sect1>
  </chapter>
  
  <chapter id="Objects">
    <title>Specifying Objects</title>
  
      <para>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.</para>
    
      <sect1 id="S41">
        <title>Object Names</title>
    
        <sect2 id="Names">
          <title>Internal and External Names</title>
    
          <para>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.</para>
        
          <para><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
            <link linkend="Field">section 4.9</link>). The second, which is preferred
            for standard APIs, is to construct a "unique name" 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
            <option>-u</option> command-line option to <code>tspec</code> (see
            <link linkend="Options">section 2.5</link>) or by setting the
            <code>UNIQUE</code> property to 1 (see
            <link linkend="Properties">section 5.4</link>).</para>
        
          <para>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:

            <programlisting>
iname | ename
            </programlisting>

            may be used to specify the internal name <code>iname</code> and
            the external name <code>ename</code>.</para>
  
          <para>For example, in the <code>stat</code> case above we could
            distinguish between the two uses as follows:

            <programlisting>
+TYPE struct stat | struct_stat ;
+FUNC int stat ( const char *, struct stat * ) ;
            </programlisting></para>

          <para>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.</para>
  
          <para>Very occasionally it may be necessary to precisely specify an
            external token name. This can be done using the form:

            <programlisting>
iname | "ename"
            </programlisting>

            which makes the object <code>iname</code> have external name
            <code>ename</code> regardless of the naming strategy used.</para>
        </sect2>
  
        <sect2 id="Identifiers">
          <title>More on Object Names</title>
  
          <para>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:

            <programlisting>
+TYPE ~t ;
+TYPEDEF ~t *t ;
            </programlisting></para>
  
          <para>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.</para>
        </sect2>
      </sect1>

      <sect1 id="Func">
        <title>+FUNC</title>
  
        <para>The simplest form of object to specify is a procedure. This is
          done by means of:

          <programlisting>
+FUNC prototype ;
          </programlisting>

          where <code>prototype</code> is the full C prototype of the
          procedure being declared. For example, <code>ansi:string.h</code>
          contains:

          <programlisting>
+FUNC char *strcpy ( char *, const char * ) ;
+FUNC int strcmp ( const char *, const char * ) ;
+FUNC size_t strlen ( const char * ) ;
          </programlisting></para>
  
        <para>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:

          <programlisting>
+FUNC int fprintf ( FILE *, const char *, ... ) ;
          </programlisting>

          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:

          <programlisting>
+FUNC (extern) prototype ;
          </programlisting>

          should be used. Thus:

          <programlisting>
+FUNC (extern) char *strcpy ( char *, const char * ) ;
          </programlisting>

          would mean that <code>strcpy</code> was only a library function and
          not a macro.</para>
  
        <para>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:

          <programlisting>
void *malloc ( sz )
size_t sz ;
          </programlisting>

          which is in general different from the prototype:

          <programlisting>
void *malloc ( size_t ) ;
          </programlisting></para>

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

          <programlisting>
+FUNC (weak) void *malloc ( size_t ) ;
          </programlisting>

          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
          <link linkend="Typedef">section 4.8</link>.)</para>
      </sect1>
  
      <sect1 id="Exp">
        <title>+EXP and +CONST</title>
  
        <para>Expressions correspond to constants, identities and variables.
          They are specified by:

          <programlisting>
+EXP type exp1, ..., expn ;
          </programlisting>

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

          <programlisting>
+EXP FILE *stdin, *stdout, *stderr ;
          </programlisting>

          specifies three expressions of type <code>FILE *</code>.</para>
  
        <para>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:

          <programlisting>
+EXP lvalue int errno ;
          </programlisting></para>

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

          <programlisting>
+EXP (extern) int errno ;
          </programlisting>

          Note that this automatically means that <code>errno</code> is an
          lvalue, so the <code>lvalue</code> qualifier is optional in this
          case.</para>
  
        <para>If all the expressions are guaranteed to be literal constants
          then one of the equivalent forms:

          <programlisting>
+EXP (const) type exp1, ..., expn ;
+CONST type exp1, ..., expn ;
          </programlisting>

          should be used. For example, in <code>ansi:errno.h</code> we have:

          <programlisting>
+CONST int EDOM, ERANGE ;
          </programlisting></para>
      </sect1>

      <sect1 id="Macro">
        <title>+MACRO</title>
  
        <para>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:

          <programlisting>
+MACRO int _toupper ( int ) ;
+MACRO int _tolower ( int ) ;
          </programlisting>

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

          <programlisting>
+MACRO void getyx ( WINDOW *win, lvalue int y, lvalue int x ) ;
          </programlisting></para>
      </sect1>

      <sect1 id="Statement">
        <title>+STATEMENT</title>
  
        <para>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:

          <programlisting>
+STATEMENT stmt ;
+STATEMENT stmt ( arg1, ..., argn ) ;
          </programlisting>

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

      <sect1 id="Define">
        <title>+DEFINE</title>
  
        <para>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:

          <programlisting>
+DEFINE name %% text %% ;
+DEFINE name ( arg1, ..., argn ) %% text %% ;
          </programlisting></para>

        <para>These translate directly into:

          <programlisting>
#define name text
#define name( arg1, ..., argn ) text
          </programlisting></para>
  
        <para>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:

          <programlisting>
+DEFINE NULL 0 ;
          </programlisting></para>
      </sect1>

      <sect1 id="Type">
        <title>+TYPE</title>
  
        <para>New types may be specified using the <code>+TYPE</code>
          construct. This has the form:

          <programlisting>
+TYPE type1, ..., typen ;
          </programlisting>

          where each <code>typei</code> has one of the forms:

          <itemizedlist>
            <listitem>
              <para><code>name</code> for a general type (about which we know
                nothing more),</para>
            </listitem>
        
            <listitem>
              <para><code>(struct) name</code> for a structure
                type,</para>
            </listitem>
        
            <listitem>
              <para><code>(union) name</code> for a union type,</para>
            </listitem>
        
            <listitem>
              <para><code>struct name</code> for a structure tag,</para>
            </listitem>
        
            <listitem>
              <para><code>union name</code> for a union tag,</para>
            </listitem>
        
            <listitem>
              <para><code>(int) name</code> for an integral type,</para>
            </listitem>
        
            <listitem>
              <para><code>(signed) name</code> for a signed integral
                type,</para>
            </listitem>
        
            <listitem>
              <para><code>(unsigned) name</code> for an unsigned integral
                type,</para>
            </listitem>
        
            <listitem>
              <para><code>(float) name</code> for a floating type,</para>
            </listitem>
        
            <listitem>
              <para><code>(arith) name</code> for an arithmetic (integral or
                floating) type,</para>
            </listitem>
        
            <listitem>
              <para><code>(scalar) name</code> for a scalar (arithmetic or
                pointer) type.</para>
            </listitem>
          </itemizedlist></para>
  
        <para>To make clear the distinction between structure types and
          structure tags, if we have in C:

          <programlisting>
typedef struct tag { int x, y ; } type ;
          </programlisting>

          then <code>type</code> is a structure type and <code>tag</code> is a
          structure tag.</para>
  
        <para>For example, in <code>ansi</code> we have:

          <programlisting>
+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 ;
          </programlisting></para>
      </sect1>

      <sect1 id="Typedef">
        <title>+TYPEDEF</title>

        <para>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
          <link linkend="Field">section 4.9</link> below.</para>
  
        <para>For example, in <code>xpg3:search.h</code> we have:

          <programlisting>
+TYPE struct entry ;
+TYPEDEF struct entry ENTRY ;
          </programlisting></para>
  
        <para>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:

          <programlisting>
+TYPEDEF ~special ( "bottom" ) ~bottom ;
+FUNC ~bottom exit ( int ) ;
          </programlisting>

          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.</para>
  
        <para>The second special form:

          <programlisting>
+TYPEDEF ~promote ( x ) y ;
          </programlisting>

          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
          <link linkend="Func">section 4.2</link>. Recall that:

          <programlisting>
void *malloc ( sz )
size_t sz ;
          </programlisting>

          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:

          <programlisting>
+TYPEDEF ~promote ( size_t ) ~size_t ;
+FUNC void *malloc ( ~size_t ) ;
          </programlisting>

          introducing a local type to stand for the integral promotion of
          <code>size_t</code>.</para>
      </sect1>

      <sect1 id="Field">
        <title>+FIELD</title>
  
        <para>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:

<programlisting>
          +FIELD type {
              ftype field1, ..., fieldn ;
              ....
          } ;
</programlisting>

          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:

          <itemizedlist>
            <listitem>
              <para><code>(struct) name</code> for a structure type,</para>
            </listitem>
        
            <listitem>
              <para><code>(union) name</code> for a union type,</para>
            </listitem>
        
            <listitem>
              <para><code>struct name</code> for a structure tag,</para>
            </listitem>
        
            <listitem>
              <para><code>union name</code> for a union tag,</para>
            </listitem>
        
            <listitem>
              <para><code>name</code> for a previously declared structure or
                union type.</para>
            </listitem>
          </itemizedlist></para>
  
        <para>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.</para>
  
        <para>For example, in <code>ansi:time.h</code> we have:

          <programlisting>
+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 ;
} ;
          </programlisting>

          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.</para>
  
        <para>As was mentioned above (in <link linkend="Names">4.1.1</link>),
          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.</para>
  
        <para>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>.</para>
  
        <para>There is a second form of the <code>+FIELD</code> construct
          which has more in common with the <code>+TYPEDEF</code> construct.
          The form:

          <programlisting>
+FIELD type := {
    ftype field1, ..., fieldn ;
    ....
} ;
          </programlisting>

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

      <sect1 id="Nat">
        <title>+NAT</title>
  
        <para>In the example given in
          <link linkend="Field">section 4.9</link>,
          <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:

          <programlisting>
+NAT nat1, ..., natn ;
          </programlisting>

          where <code>nat1</code>, ..., <code>natn</code> are the array sizes
          to be declared. The example thus becomes:

          <programlisting>
+NAT ~dirent_d_name_size ;
+FIELD struct dirent {
    char d_name [ ~dirent_d_name_size ] ;
} ;
          </programlisting>

          Note the use of a local variable to stand for a value, namely the
          array size, which is invisible to the user (see
          <link linkend="Identifiers">section 4.1.2</link>).</para>
  
        <para>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:

          <programlisting>
+NAT ~jmp_buf_size ;
+TYPE ~jmp_buf_elt ;
+TYPEDEF ~jmp_buf_elt jmp_buf [ ~jmp_buf_size ] ;
          </programlisting></para>

        <para>Again, local variables have been used for the introduced
          objects.</para>
      </sect1>

      <sect1 id="Enum">
        <title>+ENUM</title>
  
        <para>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:

          <programlisting>
+ENUM etype := {
    entry,
    ....
} ;
          </programlisting>

          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:

          <programlisting>
name
name = number
          </programlisting>

          as in a C enumeration type. For example, in
          <code>xpg3:search.h</code> we have:

          <programlisting>
+ENUM ACTION := { FIND, ENTER } ;
          </programlisting></para>
      </sect1>

      <sect1 id="Token">
        <title>+TOKEN</title>
  
        <para>As was mentioned in <link linkend="Intro">section 1</link>, 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:

          <programlisting>
+TOKEN name %% text %% ;
          </programlisting>

          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:

          <programlisting>
#pragma token text name #
          </programlisting></para>
  
        <para>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>.</para>
  
        <para>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:

          <programlisting>
+TOKEN va_arg %% PROC ( EXP lvalue : va_list : e, TYPE t ) EXP rvalue : t : %% ;
          </programlisting></para>

        <para>See reference 3 for more details on the token syntax.</para>
      </sect1>
  </chapter>
  
  <chapter id="Others">
    <title>Other tspec Constructs</title>
  
      <para>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.</para>

      <sect1 id="If">
        <title>+IF, +ELSE and +ENDIF</title>
  
        <para>It is possible to introduce conditional compilation into the API
          description by means of the constructs:

          <programlisting>
+IF %% text %%
+IFDEF %% text %%
+IFNDEF %% text %%
+ELSE
+ENDIF
          </programlisting>

          which are translated into:

          <programlisting>
#if text
#ifdef text
#ifndef text
#else /* text */
#endif /* text */
          </programlisting>

          respectively. If <code>text</code> is just a simple number or a
          single identifier the double percent delimiters may be
          excluded.</para>
  
        <para>A couple of special <code>+IFDEF</code> (and also
          <code>+IFNDEF</code>) forms are available which are useful on
          occasion. These are:

          <programlisting>
+IFDEF ~building_libs
+IFDEF ~protect ( "api", "header" )
          </programlisting>

          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
          <link linkend="Libraries">section 6.4</link>), and the protection
          macro <code>tspec</code> makes up to protect the file
          <code>api:header</code> against multiple inclusion (see
          <link linkend="Protect">section 6.2</link>).</para>
      </sect1>

      <sect1 id="Text">
        <title>Quoted Text</title>
  
        <para>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:

          <programlisting>
%% text %%
          </programlisting>

          and text for copying into the source output file in triple percents:

          <programlisting>
%%% text %%%
          </programlisting></para>
  
        <para>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.</para>
      </sect1>

      <sect1 id="Comment">
        <title>C Comments</title>
  
        <para>A special case of quoted text are C style comments:

          <programlisting>
/* text */
          </programlisting>

          which are copied directly into the include output file.</para>
      </sect1>

      <sect1 id="Properties">
        <title>File Properties</title>
  
        <para>Various properties of individual sets of objects or global
          properties can be set using file properties. These take the
          form:

          <programlisting>
$property = number ;
          </programlisting>

          for numeric (or boolean) properties, and:

          <programlisting>
$property = "string" ;
          </programlisting>

          for string properties.</para>
  
        <para>The valid property names are as follows:
          <itemizedlist>
            <listitem>
              <para><code>APINAME</code> is a string property which may be
                used to override the API name of the current set of
                objects.</para>
            </listitem>
        
            <listitem>
              <para><code>FILE</code> is a string property which is used by
                the <code>tspec</code> preprocessor to indicate the current
                input file name.</para>
            </listitem>
        
            <listitem>
              <para><code>FILENAME</code> is a string property which may be
                used to override the header name of the current set of
                objects.</para>
            </listitem>
        
            <listitem>
              <para><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
                <link linkend="Output">section 2.3</link>.  Setting the
                property to the empty string suppresses the output of this
                file.</para>
            </listitem>
        
            <listitem>
              <para><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.</para>
            </listitem>
        
            <listitem>
              <para><code>LINE</code> is a numeric property which is used by
                the <code>tspec</code> preprocessor to indicate the current
                input file line number.</para>
            </listitem>
        
            <listitem>
              <para><code>METHOD</code> is a string property which may be used
                to specify alternative construction methods for TDF library
                building (see
                <link linkend="Libraries">section 6.4</link>).</para>
            </listitem>
        
            <listitem>
              <para><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
                <link linkend="Names">section 4.1.1</link>).</para>
            </listitem>
        
            <listitem>
              <para><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
                <link linkend="Protect">section 6.2</link>). Setting the
                property to the empty string suppresses this macro.</para>
            </listitem>
        
            <listitem>
              <para><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
                <link linkend="Output">section 2.3</link>.  Setting the
                property to the empty string suppresses the output of this
                file.</para>
            </listitem>
        
            <listitem>
              <para><code>SUBSETNAME</code> is a string property which may be
                used to override the subset name of the current set of
                objects.</para>
            </listitem>
        
            <listitem>
              <para><code>UNIQUE</code> is a numeric property which may be
                used to switch the unique token name flag on and off (see
                <link linkend="Names">section 4.1.1</link>). For standard APIs
                it is recommended that this property is set to 1 in the API
                <code>MASTER</code> file.</para>
            </listitem>
        
            <listitem>
              <para><code>VERBOSE</code> is a numeric property which may be
                used to set the level of the verbose option (see
                <link linkend="Options">section 2.5</link>).</para>
            </listitem>
        
            <listitem>
              <para><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.</para>
            </listitem>
          </itemizedlist></para>
      </sect1>
  </chapter>
  
  <chapter id="S6">
    <title>Miscellaneous Topics</title>
  
      <para>In this section we round up a few miscellaneous topics.</para>
  
      <sect1 id="FineImpl">
        <title>Fine Control of Included Files</title>
  
        <para>The <code>+IMPLEMENT</code> and <code>+USE</code> commands
          described in <link linkend="Impl">section 3.2</link> 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:

          <programlisting>
+IMPLEMENT "api" (key) ;
+IMPLEMENT "api", "header" (key) ;
+IMPLEMENT "api", "header", "subset" (key) ;
          </programlisting>

          with corresponding forms for <code>+USE</code>.  <code>key</code>
          specifies which output files the inclusion commands should appear
          in. It can be:
  
          <itemizedlist>
            <listitem>
              <para><code>??</code>, indicating neither output file,</para>
            </listitem>
        
            <listitem>
              <para><code>!?</code>, indicating the include output file
                only,</para>
            </listitem>
        
            <listitem>
              <para><code>?!</code>, indicating the source output file
                only,</para>
            </listitem>
        
            <listitem>
              <para><code>!!</code>, indicating both output files (this is the
                same as the normal form).</para>
            </listitem>
          </itemizedlist></para>
  
        <para>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:

          <programlisting>
+BASE_API ;
          </programlisting>

          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:

          <programlisting>
+USE ( "api" ), "header" ;
          </programlisting>

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

      <sect1 id="Protect">
        <title>Protection Macros</title>
  
        <para>Each include output file is surrounded by a construct of the
          form:

          <programlisting>
#ifndef MACRO
#define MACRO
....
#endif /* MACRO */
          </programlisting>

          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
          <link linkend="Properties">section 5.4</link>). Setting
          <code>PROTECT</code> to the empty string suppresses the protection
          construct altogether.  (Also see
          <link linkend="If">section 5.1</link>.)</para>
      </sect1>

      <sect1 id="Index">
        <title>Index Printing</title>

        <para>If it is invoked with the <option>-i</option> 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.</para>
      </sect1>

      <sect1 id="Libraries">
        <title>TDF Library Building</title>
  
        <para>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
          <link linkend="If">section 5.1</link>).</para>
  
        <para>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:

          <programlisting>
#pragma implement interface &lt;../api/header&gt;
#include &lt;header&gt;
          </programlisting>

          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 <link linkend="Output">section 2.3</link>). 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>.</para>
  
        <para>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
          <link linkend="Properties">section 5.4</link>) 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:

          <programlisting>
$METHOD = "TNC" ;
+MACRO double fl_abs ( double ) ;
%%%
    ( make_tokdef fl_abs ( exp x ) exp
        ( floating_abs impossible x ) )
%%%
          </programlisting></para>
  
        <para>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:

          <programlisting>
( make_tokdef fl_abs ( exp x ) exp
    ( floating_abs impossible x ) )
          </programlisting>

          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.</para>
      </sect1>
  </chapter>
  
  <chapter id="S7">
    <title>Changes in tspec 2.0</title>
  
      <para>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:
        <itemizedlist>
          <listitem>
            <para>The added specification level of named subsets of headers
              has been introduced (see
              <link linkend="Levels">section 2.1</link>).  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.</para>
          </listitem>
      
          <listitem>
            <para>A number of new command-line options have been added, and
              some of the existing options have been modified slightly (see
              <link linkend="Options">section 2.5</link>).</para>
          </listitem>
      
          <listitem>
            <para>The suffix <code>.api</code> has been added to the output
              directories (see <link linkend="Output">section 2.3</link>) to
              avoid possible confusion with other include file
              directories.</para>
          </listitem>
      
          <listitem>
            <para>The use of identifiers beginning with <code>~</code> as
              local variables is new (see <link linkend="Identifiers">section
              4.1.2</link>).</para>
          </listitem>
      
          <listitem>
            <para>The <code>+STATEMENT</code> and <code>+DEFINE</code>
              constructs (see <link linkend="Statement">section 4.5</link> and
              <link linkend="Define">section 4.6</link>) are new.</para>
          </listitem>
      
          <listitem>
            <para>The <code>(extern)</code>, <code>(weak)</code> and
              <code>(const)</code> qualifiers for <code>+FUNC</code> and
              <code>+EXP</code> (see <link linkend="Func">section 4.2</link> and
              <link linkend="Exp">section 4.3</link>) are new.</para>
          </listitem>
      
          <listitem>
            <para>The <code>(signed)</code> and <code>(unsigned)</code>
              qualifiers for <code>+TYPE</code> (see
              <link linkend="Type">section 4.7</link>) are new.</para>
          </listitem>
      
          <listitem>
            <para>The <code>~special</code> type constructor (see
              <link linkend="Typedef">section 4.8</link>) is new.</para>
          </listitem>
      
          <listitem>
            <para>The <code>~abstract</code> type constructor has been
              abandoned.</para>
          </listitem>
      
          <listitem>
            <para>The <code>+BASE_API</code> command described in
              <link linkend="FineImpl">section 6.1</link> is new.</para>
          </listitem>
      
          <listitem>
            <para>The indexing routines (see
              <link linkend="Index">section 6.3</link>) have been greatly
              improved.</para>
          </listitem>
        </itemizedlist></para>
  </chapter>
  
    <chapter id="S8">
      <title>References</title>
    
      <para><remark>"TDF and Portability"</remark>, DRA, 1993.</para>
    
      <para><remark>"The TDF Notation Compiler"</remark>, DRA, 1993.</para>
    
      <para><remark>"The C to TDF Producer"</remark>, DRA, 1993.</para>
  </chapter>
</book>