Oracle Call Interface Programmer's Guide, Volumes 1 & 2 Release 8.0 A58234-01 |
Library | Product | Contents | Index

# 12
Using the Object Type Translator

This chapter discusses the Object Type Translator (OTT), which is used to map database object types and named collection types to C structs for use in OCI and
Pro*C/C++ applications. The chapter includes the following sections:

- OTT Overview
- Using the Object Type Translator
- Using the OTT with OCI Applications
- OTT Reference

  Note: For information specific to Pro*C/C++, please refer to the Pro*COBOL Precompiler Programmer's Guide.

  Note: The functionality described in this chapter is only available if you have purchased the Oracle8 Enterprise Edition with the Objects Option.

## OTT Overview

OTT (The Object Type Translator) is a new product released with Oracle8. It assists in the development of C language applications which make use of user-defined types in an Oracle8 server.

Through the use of SQL CREATE TYPE statements, you can create object types. The definitions of these types are stored in the database, and can be used in the creation of database tables. Once these tables are populated, an OCI or Pro*C/C++ programmer can access objects stored in the tables.

An application which accesses object data needs to be able to represent the data in a host language format. This is accomplished by representing object types as C structs. It would be possible for a programmer to code struct declarations by hand to represent database object types, but this can be very time-consuming and error-prone if many types are involved. The OTT simplifies this step by automatically generating appropriate struct declarations. For Pro*C/C++, the application only needs to include the header file generated by the OTT. In OCI, the application also needs to call an initialization function generated by the OTT.

In addition to creating structs which represent stored datatypes, the OTT also generates parallel indicator structs which indicate whether an object type or its fields are null.

## Using the Object Type Translator

The Object Type Translator (OTT) converts database definitions of object types and named collection types into C struct declarations which can be included in an OCI or Pro*C/C++ application.

You must explicitly invoke the OTT to translate database types to C representations. You must also initialize a data structure called the Type Version Table with information about the user-defined types required by the program. Code to perform this initialization is generated by the OTT.

On most operating systems, the OTT is invoked on the command line. It takes as input an intype file, and it generates an outtype file and one or more C header files and an optional implementation file. The following is an example of a command which invokes the OTT:

    ott userid=scott/tiger intype=demoin.typ outtype=demoout.typ code=c hfile=demo.h

This command causes the OTT to connect to the database with username ``scott`' and password ``tiger`', and translate database types to C structs, based on instructions in the `intype` file (`demoin.typ`). The resulting structs are output to the header file (`demo.h`), for the host language (C) specified by the `code` parameter. The outtype file (`demoout.typ`) receives information about the translation.

Each of these parameters is described in more detail in later sections of this chapter.

Sample demoin.typ file:

    CASE=LOWER
    TYPE employee

Sample demoout.typ file:

    CASE = LOWER
    TYPE EMPLOYEE AS employee
      VERSION = "$8.0"
      HFILE = demo.h

In this example, the `demoin.typ` file contains the type to be translated, preceded by TYPE (e.g., TYPE employee). The structure of the outtype file is similar to the `intype` file, with the addition of information obtained by the OTT.

Once the OTT has completed the translation, the header file contains a C struct representation of each type specified in the intype file, and a null indicator struct corresponding to each type. For example, if the employee type listed in the intype file was defined as

    CREATE TYPE employee AS OBJECT
    (
        name       VARCHAR2(30),
        empno      NUMBER,
        deptno     NUMBER,
        hiredate   DATE,
        salary      NUMBER
    );

the header file generated by the OTT (`demo.h`) includes, among other items, the following declarations:

    struct employee
    {
        OCIString * name;
        OCINumber empno;
        OCINumber deptno;
        OCIDate   hiredate;
        OCINumber salary;
    };
    typedef struct emp_type emp_type;

    struct employee_ind
    {
        OCIInd _atomic;
        OCIInd name;
        OCIInd empno;
        OCIInd deptno;
        OCIInd hiredate;
        OCIInd salary;
    };
    typedef struct employee_ind employee_ind;

    Note: Parameters in the intype file control the way generated structs are named. In this example, the struct name employee matches the database type name employee. The struct name is in lower case because of the line CASE=lower in the intype file.

    The datatypes which appear in the struct declarations (e.g., OCIString, OCIInd) are special datatypes which are new to Oracle8. For more information about these types, see the section "OTT Datatype Mappings" on page  12-9.

The following sections describe these aspects of using the OTT:

- Creating Types in the Database
- Invoking the OTT
- The OTT Command Line
- The Intype File
- OTT Datatype Mappings
- Null Indicator Structs
- The Outtype File

The remaining sections of the chapter discuss the use of the OTT with OCI, followed by a reference section which describes command line syntax, parameters, intype file structure, nested #include file generation, schema names usage, default name mapping, and restrictions.

### Creating Types in the Database

The first step in using the OTT is to create object types or named collection types and store them in the database. This is accomplished through the use of the SQL CREATE TYPE statement.

  See Also: For information about the CREATE TYPE statement, refer to the Oracle8 SQL Reference.

### Invoking the OTT

The next step is to invoke the OTT. OTT parameters can be specified on the command line, or in a file called a configuration file. Certain parameters can also be specified in the INTYPE file.

If a parameter is specified in more than one place, its value on the command line will take precedence over its value in the INTYPE file, which takes precedence over its value in a user-defined configuration file, which takes precedence over its value in the default configuration file.

#### Command Line

Parameters (also called options) set on the command line override any set elsewhere. See the next section, "The OTT Command Line", for more information.

#### Configuration File

A configuration file is a text file that contains OTT parameters. Each non-blank line in the file contains one parameter, with its associated value or values. If more than one parameter is put on a line, only the first one will be used. No whitespace may occur on any non-blank line of a configuration file.

A configuration file may be named on the command line. In addition, a default configuration file is always read. This default configuration file must always exist, but can be empty. The name of the default configuration file is ottcfg.cfg, and the location of the file is system-specific. For example, on Solaris, the file specification is $ORACLE_HOME/precomp/admin/ottcfg.cfg. See your platform-specific documentation for further information.

#### INTYPE File

The INTYPE file gives a list of types for the OTT to translate.

The parameters CASE, HFILE, INITFUNC, and INITFILE can appear in the INTYPE file. See "The Intype File" on page 12-8 for more information.

## The OTT Command Line

On most platforms, the OTT is invoked on the command line. You can specify the input and output files, and the database connection information, among other things. Consult your platform-specific documentation to see how to invoke the OTT on your platform.

##### Example 1

The following is an example of an OTT invocation from the command line:

    ott userid=bren/bigkitty intype=demoin.typ outtype=demoout.typ code=c hfile=demo.h

Note: No spaces are permitted around the equals sign (=).

The following sections describe the elements of the command line used in this example.

For a detailed discussion of the various OTT command line options, please refer to the section "OTT Reference" on page 12-22.

### OTT

Causes the OTT to be invoked. It must be the first item on the command line.

### userid

Specifies the database connection information which the OTT will use.

In Example 1, the OTT will attempt to connect with username ``bren`' and password ``bigkitty`'.

### intype

Specifies the name of the intype file which will be used.

In Example 1, the name of the intype file is specified as `demoin.typ`.

### outtype

Specifies the name of the outtype file. When the OTT generates the C header file, it also writes information about the translated types into the outtype file. This file contains an entry for each of the types which is translated, including its version string, and the header file to which its C representation was written.

In "Example 1" on page 12-6, the name of the outtype file is specified as `demoout.typ`.

  Note: If the file specified by the `outtype` keyword already exists, it is overwritten when the OTT runs. If the name of the outtype file is the same as the name of the intype file, the outtype information overwrites the intype file.

### code

Specifies the target language for the translation. The following options are available:

- C (equivalent to ANSI_C)
- ANSI_C (for ANSI C)
- KR_C (for Kernighan & Ritchie C)

There is currently no default option, so this parameter is required.

Struct declarations are identical in both C dialects. The style in which the initialization function defined in the INITFILE file is defined depends on whether KR_C is used. If the INITFILE option is not used, all three options are equivalent.

### hfile

Specifies the name of the C header file to which the generated structs should be written.

In "Example 1" on page 12-6, the generated structs will be stored in a file called `demo.h`.

  Note: If the file specified by the `hfile` keyword already exists, it will be overwritten when the OTT runs, with one exception: if the contents of the file as generated by the OTT are identical to the previous contents of the file, the OTT will not actually write to the file. This preserves the modification time of the file so that UNIX make and similar facilities on other platforms do not perform unnecessary recompilations.

### initfile

Specifies the use of the C source file into which the type initialization function is to be written.

  Note: If the file specified by the `initfile` keyword already exists, it will be overwritten when the OTT runs, with one exception: if the contents of the file as generated by the OTT are identical to the previous contents of the file, the OTT will not actually write to the file. This preserves the modification time of the file so that UNIX make and similar facilities on other platforms do not perform unnecessary recompilations.

### initfunc

Specifies the name of the initialization function to be defined in the initfile.

If this parameter is not used and an initialization function is generated, the name of the initialization function will be the same as the base name of the initfile.

## The Intype File

When running the OTT, the INTYPE file tells the OTT which database types should be translated, and it can also control the naming of the generated structs. The intype file can be a user-created file, or it may be the outtype file of a previous invocation of the OTT. If the INTYPE parameter is not used, all types in the schema to which the OTT connects are translated.

The following is a simple example of a user-created intype file:

    CASE=LOWER
    TYPE employee
      TRANSLATE SALARY$ AS salary
                DEPTNO AS department
    TYPE ADDRESS
    TYPE item
    TYPE "Person"
    TYPE PURCHASE_ORDER AS p_o

The first line, with the CASE keyword, indicates that generated C identifiers should be in lower case. However, this CASE option is only applied to those identifiers that are not explicitly mentioned in the intype file. Thus, employee and ADDRESS would always result in C structures `employee` and `ADDRESS`, respectively. The members of these structures would be named in lower case.

  See Also: See the description of "case" on page 12-27 for further information regarding the CASE option.

The lines which begin with the TYPE keyword specify which types in the database should be translated: in this case, the `EMPLOYEE`, `ADDRESS`, `ITEM`, `PERSON`, and `PURCHASE_ORDER` types.

The TRANSLATE...AS keywords specify that the name of an object attribute should be changed when the type is translated into a C struct. In this case, the SALARY$ attribute of the employee type is translated to `salary`.

The AS keyword in the final line specifies that the name of an object type should be changed when it is translated into a struct. In this case, the `purchase_order` database type is translated into a struct called `p_o`.

If AS is not used to translate a type or attribute name, the database name of the type or attribute will be used as the C identifier name, except that the CASE option will be observed, and any characters that cannot be mapped to a legal C identifier character will be replaced by an underscore. Reasons for translating a type or attribute name include:

- the name contains characters other than letters, digits, and underscores
- the name conflicts with a C keyword
- the type name conflicts with another identifier in the same scope.
  This may happen, for example, if the program uses two types with the same name from different schemas.
- the programmer prefers a different name

The OTT may need to translate additional types which are not listed in the intype file. This is because the OTT analyzes the types in the intype file for type dependencies before performing the translation, and translates other types as necessary. For example, if the `ADDRESS` type were not listed in the intype file, but the `"Person"` type had an attribute of type `ADDRESS`, the OTT would still translate `ADDRESS` because it is required to define the `"Person"` type.

A normal case-insensitive SQL identifier can be spelled in any combination of upper and lower case in the INTYPE file, and is not quoted.

Use quotation marks, such as TYPE "Person", to reference SQL identifiers that have been created in a case-sensitive manner, e.g., CREATE TYPE "Person". A SQL identifier is case-sensitive if it was quoted when it was declared. Quotation marks can also be used to refer to a SQL identifier that is an OTT-reserved word, e.g., TYPE "CASE". When a name is quoted for this reason, the quoted name must be in upper case if the SQL identifier was created in a case-insensitive manner, e.g., CREATE TYPE Case. If an OTT-reserved word is used to refer to the name of a SQL identifier but is not quoted, the OTT will report a syntax error in the INTYPE file.

  See Also: For a more detailed specification of the structure of the intype file and the available options, refer to the section "Structure of the Intype File" on page 12-29.

## OTT Datatype Mappings

When the OTT generates a C struct from a database type, the struct contains one element corresponding to each attribute of the object type. The datatypes of the attributes are mapped to types which are used in Oracle8's object data types. The datatypes found in Oracle8 include a set of predefined, primitive types, and provide for the creation of user-defined types, like object types and collections.

The set of predefined types in Oracle8 includes standard types which are familiar to most programmers, including number and character types. It also includes new datatypes being introduced with Oracle8 (e.g., BLOB, CLOB).

Oracle8 also includes a set of predefined types which are used to represent object type attributes in C structs. As an example, consider the following object type definition, and its corresponding OTT-generated struct declarations:

    CREATE TYPE employee AS OBJECT
    (   name       VARCHAR2(30),
        empno      NUMBER,
        deptno     NUMBER,
        hiredate   DATE,
        salary$    NUMBER);

The OTT output, assuming CASE=LOWER and no explicit mappings of type or attribute names, is:

    struct employee
    {   OCIString * name;
        OCINumber empno;
        OCINumber department;
        OCIDate   hiredate;
        OCINumber salary_;
    };
    typedef struct emp_type emp_type;
    struct employee_ind
    {
        OCIInd _atomic;
        OCIInd name;
        OCIInd empno;
        OCIInd department;
        OCIInd hiredate;
        OCIInd salary_;
    }
    typedef struct employee_ind employee_ind;

The indicator struct (struct employee_ind) is explained in the section, "Null Indicator Structs" on page 12-15.

The datatypes in the struct declarations-OCIString, OCINumber, OCIDate, OCIInd-are new C mappings of object types being introduced with Oracle8. They are used here to map the datatypes of the object type attributes. The number datatype of the `empno` attribute, maps to the new OCINumber datatype, for example. These new datatypes can also be used as the types of bind and define variables.

#### Mapping Object Datatypes to C

This section describes the mappings of Oracle8 object attribute types to C types generated by the OTT. The following section "OTT Type Mapping Example" on page 12-12 includes examples of many of these different mappings. The following table lists the mappings from types which can be used as attributes to object datatypes which are generated by the OTT.

##### Table 12-1 Object Datatype Mappings for Object Type Attributes

Object Attribute Types | C Mapping
--- | ---
VARCHAR2(N) | OCIString *
VARCHAR(N) | OCIString *
CHAR(N), CHARACTER(N) | OCIString *
NUMBER, NUMBER(N), NUMBER(N,N) | OCINumber
NUMERIC, NUMERIC(N), NUMERIC(N,N) | OCINumber
REAL | OCINumber
INT, INTEGER, SMALLINT | OCINumber
FLOAT, FLOAT(N), DOUBLE PRECISION | OCINumber
DEC, DEC(N), DEC(N,N) | OCINumber
DECIMAL, DECIMAL(N), DECIMAL(N,N) | OCINumber
DATE | OCIDate
BLOB | OCIBlobLocator *
CLOB | OCIClobLocator *
BFILE | OCIBfileLocator *
Nested Object Type | C name of the nested object type
REF | declared using typedef; equivalent to OCIRef * See the following example.
RAW(N) | OCIRaw *

The next table shows the mappings of named collection types to Oracle8 object datatypes generated by the OTT:

##### Table 12-2 Object Datatype Mappings for Collection Types

Named Collection Type | C Mapping
--- | ---
VARRAY | declared using typedef; equivalent to OCIArray * See the following example.
NESTED TABLE | declared using typedef; equivalent to OCITable * See the following example.

  Note: For REF, VARRAY, and NESTED TABLE types, the OTT generates a typedef. The type declared in the typedef is then used as the type of the data member in the struct declaration. For examples, see the next section, "OTT Type Mapping Example".

If an object type includes an attribute of a REF or collection type, a typedef for the REF or collection type is first generated. Then the struct declaration corresponding to the object type is generated. The struct includes an element whose type is a pointer to the REF or collection type.

If an object type includes an attribute whose type is another object type, the OTT first generates the nested type. It then maps the object type attribute to a nested struct of the type of the nested object type.

The Oracle8 C datatypes to which the OTT maps non-object database attribute types are structures, which, except for OCIDate, are opaque.

#### OTT Type Mapping Example

The following example is presented to demonstrate the various type mappings created by the OTT.

Given the following database types

    CREATE TYPE my_varray AS VARRAY(5) of integer;

    CREATE TYPE object_type AS OBJECT
    (object_name    VARCHAR2(20));

    CREATE TYPE my_table AS TABLE OF object_type;

    CREATE TYPE many_types AS OBJECT
    ( the_varchar    VARCHAR2(30),
      the_char       CHAR(3),
      the_blob       BLOB,
      the_clob       CLOB,
      the_object     object_type,
      another_ref    REF other_type,
      the_ref        REF many_types,
      the_varray     my_varray,
      the_table      my_table,
      the_date       DATE,
      the_num        NUMBER,
      the_raw        RAW(255));

and an intype file which includes

    CASE = LOWER
    TYPE many_types

the OTT would generate the following C structs:

  Note: Comments are provided here to help explain the structs. These comments are not part of actual OTT output.

    #ifndef MYFILENAME_ORACLE
    #define MYFILENAME_ORACLE

    #ifndef OCI_ORACLE
    #include <oci.h>
    #endif

    typedef OCIRef many_types_ref;
    typedef OCIRef object_type_ref;
    typedef OCIArray my_varray;            /* part of many_types */
    typedef OCITable my_table;             /* part of many_types*/
    typedef OCIRef other_type_ref;
    struct object_type                     /* part of many_types */
    {
       OCIString * object_name;
    };
    typedef struct object_type object_type;

    struct object_type_ind               /*indicator struct for*/
    {                                            /*object_types*/
       OCIInd _atomic;
       OCIInd object_name;
    };
    typedef struct object_type_ind object_type_ind;

    struct many_types
    {
       OCIString *        the_varchar;
       OCIString *        the_char;
       OCIBlobLocator *   the_blob;
       OCIClobLocator *   the_clob;
       struct object_type the_object;
       other_type_ref *   another_ref;
       many_types_ref *   the_ref;
       my_varray *        the_varray;
       my_table *         the_table;
       OCIDate            the_date;
       OCINumber          the_num;
       OCIRaw *           the_raw;
    };
    typedef struct many_types many_types;

    struct many_types_ind                  /*indicator struct for*/
    {                                               /*many_types*/
       OCIInd _atomic;
       OCIInd the_varchar;
       OCIInd the_char;
       OCIInd the_blob;
       OCIInd the_clob;
       struct object_type_ind the_object;              /*nested*/
       OCIInd another_ref;
       OCIInd the_ref;
       OCIInd the_varray;
       OCIInd the_table;
       OCIInd the_date;
       OCIInd the_num;
       OCIInd the_raw;
    };
    typedef struct many_types_ind many_types_ind;

    #endif

Notice that even though only one item was listed for translation in the intype file, two object types and two named collection types were translated. As described in the section "The OTT Command Line" on page 12-6, the OTT automatically translates any types which are used as attributes of a type being translated, in order to complete the translation of the listed type.

This is not the case for types which are only accessed by a pointer or ref in an object type attribute. For example, although the `many_types` type contains the attribute `another_ref REF other_type`, a declaration of struct `other_type` was not generated.

This example also illustrates how typedefs are used to declare VARRAY, NESTED TABLE, and REF types.

The typedefs occur near the beginning:

    typedef OCIRef many_types_ref;
    typedef OCIRef object_type_ref;
    typedef OCIArray my_varray;
    typedef OCITable my_table;
    typedef OCIRef other_type_ref;

In the struct many_types, the VARRAY, NESTED TABLE, and REF attributes are declared:

    struct many_types
    {   ...
       other_type_ref *   another_ref;
       many_types_ref *   the_ref;
       my_varray *        the_varray;
       my_table *         the_table;
       ...
    }

### Null Indicator Structs

Each time the OTT generates a C struct to represent a database object type, it also generates a corresponding null indicator struct. When an object type is selected into a C struct, null indicator information may be selected into a parallel struct.

For example, the following null indicator struct was generated in the example in the previous section:

    struct many_types_ind
    {
    OCIInd _atomic;
    OCIInd the_varchar;
    OCIInd the_char;
    OCIInd the_blob;
    OCIInd the_clob;
    struct object_type_ind the_object;
    OCIInd another_ref;
    OCIInd the_ref;
    OCIInd the_varray;
    OCIInd the_table;
    OCIInd the_date;
    OCIInd the_num;
    OCIInd the_raw;
    };
    typedef struct many_types_ind many_types_ind;

The layout of the null struct is important. The first element in the struct (`_atomic`) is the atomic null indicator. This value indicates the null status for the object type as a whole. The atomic null indicator is followed by an indicator element corresponding to each element in the OTT-generated struct representing the object type.

Notice that when an object type contains another object type as part of its definition (in the above example it is the `object_type` attribute), the indicator entry for that attribute is the null indicator struct (`object_type_ind`) corresponding to the nested object type.

VARRAYs and NESTED TABLEs contain the null information for their elements.

The datatype for all other elements of a null indicator struct is OCIInd.

  See Also: For more information about atomic nullness, refer to the section "Nullness" on page 8-28.

## The Outtype File

The outtype file is named on the OTT command line. When the OTT generates the C header file, it also writes the results of the translation into the outtype file. This file contains an entry for each of the types which is translated, including its version string, and the header file to which its C representation was written.

The outtype file from one OTT run can be used as the intype file for a subsequent OTT invocation.

For example, given the simple intype file used earlier in this chapter

    CASE=LOWER
    TYPE employee
      TRANSLATE SALARY$ AS salary
                DEPTNO AS department
    TYPE ADDRESS
    TYPE item
    TYPE person
    TYPE PURCHASE_ORDER AS p_o

the user has chosen to specify the case for OTT-generated C identifiers, and has provided a list of types which should be translated. In two of these types, naming conventions are specified.

The following is an example of what the outtype file might look like after running the OTT:

    CASE = LOWER
    TYPE EMPLOYEE AS employee
      VERSION = "$8.0"
      HFILE = demo.h
      TRANSLATE SALARY$ AS salary
                 DEPTNO AS department
    TYPE ADDRESS AS ADDRESS
      VERSION = "$8.0"
      HFILE = demo.h
    TYPE ITEM AS item
      VERSION = "$8.0"
      HFILE = demo.h
    TYPE "Person" AS Person
      VERSION = "$8.0"
      HFILE = demo.h
    TYPE PURCHASE_ORDER AS p_o
      VERSION = "$8.0"
      HFILE = demo.h

When examining the contents of the outtype file, you might discover types listed which were not included in the intype specification. For example, if the intype file only specified that the `person` type was to be translated

    CASE = LOWER
    TYPE PERSON

and the definition of the person type includes an attribute of type `address`, then the outtype file will include entries for both `PERSON` and `ADDRESS`. The `person` type cannot be translated completely without first translating `address`.

As described in the section "The OTT Command Line" on page 12-6, the OTT analyzes the types in the intype file for type dependencies before performing the translation, and translates other types as necessary.

## Using the OTT with OCI Applications

C header and implementation files which have been generated by the OTT can be used by an OCI application that accesses objects in an Oracle8 server. The header file is incorporated into the OCI code with an `#include` statement.

Once the header file has been included, the OCI application can access and manipulate object data in the host language format.

shows the steps involved in using the OTT with the OCI:

1. SQL is used to create type definitions in the database.
2. The OTT generates a header file containing C representations of object types and named collection types. It also generates an implementation file, as named with the INITFILE option.
3. The application is written. User-written code in the OCI application declares and calls the INITFUNC function.
4. The header file is included in an OCI source code file.
5. The OCI application, including the implementation file generated by the OTT, is compiled and linked with the OCI libraries.
6. The OCI executable is run against the Oracle8 server.

   #### Figure 12-1 Using the OTT with OCI

### Accessing and Manipulating Objects with OCI

Within the application, the OCI program can perform bind and define operations using program variables declared to be of types which appear in the OTT-generated header file.

For example, an application might fetch a REF to an object using a SQL SELECT statement and then pin that object using the appropriate OCI function. Once the object has been pinned, its attribute data can be accessed and manipulated with other OCI functions.

OCI includes a set of datatype mapping and manipulation functions which are specifically designed to work on attributes of object types and named collection types.

The following are examples of the available functions:

- OCIStringSize() gets the size of an OCIString string.
- OCINumberAdd() adds two OCINumber numbers together.
- OCILobIsEqual() compares two LOB locators for equality.
- OCIRawPtr() gets a pointer to an OCIRaw raw datatype.
- OCICollAppend() appends an element to a collection type (OCIArray or OCITable).
- OCITableFirst() returns the index for the first existing element of a nested table (OCITable).
- OCIRefIsNull() tests if a REF (OCIRef) is null

These functions are described in detail in other chapters of this guide.

### Calling the Initialization Function

The OTT generates a C initialization function if requested. The initialization function tells the environment, for each object type used in the program, which version of the type is used. You may specify a name for the initialization function when invoking the OTT with the INITFUNC option, or may allow the OTT to select a default name based on the name of the implementation file (INITFILE) containing the function.

The initialization function takes two arguments, an environment handle pointer and an error handle pointer. There is typically a single initialization function, but this is not required. If a program has several separately compiled pieces requiring different types, you may want to execute the OTT separately for each piece requiring, for each piece, one initialization file, containing an initialization function.

After an environment handle is created by an explicit OCI object call, for example, by calling OCIEnvInit(), you must also explicitly call the initialization functions. All the initialization functions must be called for each explicitly created environment handle. This gives each handle access to all the Oracle8 datatypes used in the entire program.

If an environment handle is implicitly created via embedded SQL statements, such as EXEC SQL CONTEXT USE and EXEC SQL CONNECT, the handle is initialized implicitly, and the initialization functions need not be called. This is only relevant when Pro*C/C++ is being combined with OCI applications.

The following example shows and initialization function.

Given an intype file, ex2c.typ, containing

    TYPE BREN.PERSON

    TYPE BREN.ADDRESS

and the command line

    ott userid=bren/bigkitty intype=ex2c outtype=ex2co hfile=ex2ch.h
    initfile=ex2cv.c

the OTT generates the following to the file ex2cv.c:

    #ifndef OCI_ORACLE
    #include <oci.h>
    #endif

    sword ex2cv(OCIEnv *env, OCIError *err)
    {
       sword status = OCITypeVTInit(env, err);
       if (status == OCI_SUCCESS)
          status = OCITypeVTInsert(env, err,
              "BREN", 5,
              "PERSON", 6,
              "$8.0", 4);
        if (status == OCI_SUCCESS)
            status = OCITypeVTInsert(env, err,
               "BREN", 5,
               "ADDRESS", 7,
               "$8.0", 4);
        return status;
    }

The function ex2cv creates the type version table and inserts the types BREN.PERSON and BREN.ADDRESS.

If a program explicitly creates an environment handle, all the initialization functions must be generated, compiled, and linked, because they must be called for each explicitly created handle. If a program does not explicitly create any environment handles, initialization functions are not required.

A program that uses an OTT-generated header file must also use the initialization function generated at the same time. More precisely, if a header file generated by the OTT is included in a compilation that generates code that is linked into program P, and an environment handle is explicitly created somewhere in program P, the implementation file generated by the same invocation of the OTT must also be compiled and linked into program P. Doing this correctly is the user's responsibility.

### Tasks of the Initialization Function

The C initialization function supplies version information about the types processed by the OTT. It adds to the type-version table the name and version identifier of every OTT-processed object datatype.

The type-version table is used by Oracle's type manager to determine which version of a type a particular program uses. Different initialization functions generated by the OTT at different times may add some of the same types to the type version table. When a type is added more than once, Oracle ensures the same version of the type is registered each time.

It is the OCI programmer's responsibility to declare a function prototype for the initialization function, and to call the function.

  Note: In the current release of Oracle8, each type has only one version. Initialization of the type version table is required only for compatibility with future releases of Oracle8.

## OTT Reference

Behavior of the OTT is controlled by parameters which can appear on the OTT command line or in a CONFIG file. Certain parameters may also appear in the INTYPE file.

This section provides detailed information about the following topics:

- OTT Command Line Syntax
- OTT Parameters
- Where OTT Parameters Can Appear
- Structure of the Intype File
- Nested #include File Generation
- SCHEMA_NAMES Usage
- Default Name Mapping
- Restrictions

The following conventions are used in this chapter to describe OTT syntax:

- Angle brackets (<...>) enclose strings to be supplied by the user.
- Strings in UPPERCASE are entered as shown, except that case is not significant.
- OTT keywords are listed in a lower-case monospaced font in examples and headings, but are printed in upper-case in text to make them more distinctive.
- Square brackets [...] enclose optional items.
- An ellipsis (...) immediately following an item (or items enclosed in brackets) means that the item can be repeated any number of times.
- Punctuation symbols other than those described above are entered as shown. These include `.', `@', etc.

### OTT Command Line Syntax

The OTT command-line interface is used when explicitly invoking the OTT to translate database types into C structs. This is always required when developing OCI applications that use objects.

An OTT command line statement consists of the keyword `OTT`, followed by a list of OTT parameters.

The parameters which can appear on an OTT command line statement are as follows:

  [`userid`=<username>/<password>[@<db_name>]]

  [`intype`=<in_filename>]

  `outtype`=<out_filename>

  `code`=<C|ANSI_C|KR_C>

  [`hfile`=<filename>]

  [`errtype`=<filename>]

  [`config`=<filename>]

  [`initfile`=<filename>]

  [`initfunc`=<filename>]

  [`case`=<SAME|LOWER|UPPER|OPPOSITE>]

  [`schema_name`=<ALWAYS|IF_NEEDED|FROM_INTYPE>]

  Note: Generally, the order of the parameters following the OTT command does not matter, and only the OUTTYPE and CODE parameters are always required.

  The HFILE parameter is almost always used. If omitted, HFILE must be specified individually for each type in the INTYPE file. If the OTT determines that a type not listed in the INTYPE file must be translated, an error will be reported. Therefore, it is safe to omit the HFILE parameter only if the INTYPE file was previously generated as an OTT OUTTYPE file.

  If the INTYPE file is omitted, the entire schema will be translated. See the parameter descriptions in the following section for more information.

The following is an example of an OTT command line statement:

    OTT userid=marc/cayman intype=in.typ outtype=out.typ code=c hfile=demo.h
    errtype=demo.tls case=lower

Each of the OTT command line parameters is described in the following sections.

### OTT Parameters

Enter parameters on the OTT command line using the following format:

parameter=value

where parameter is the literal parameter string and value is a valid parameter setting. The literal parameter string is not case sensitive.

Separate command-line parameters using either spaces or tabs.

Parameters can also appear within a configuration file, but, in that case, no whitespace is permitted within a line, and each parameter must appear on a separate line. Additionally, the parameters CASE, HFILE, INITFUNC, and INITFILE can appear in the INTYPE file.

#### userid

The USERID parameter specifies the Oracle username, password, and optional database name (Net8 database specification string). If the database name is omitted, the default database is assumed. The syntax of this parameter is:

`userid`=<username/password[@db_name]>

If this is the first parameter, "USERID=" may be omitted as shown here:

`OTT` username/password...

The USERID parameter is optional. If omitted, the OTT automatically attempts to connect to the default database as user OPS$username, where username is the user's operating system user name.

#### intype

The INTYPE parameter specifies the name of the file from which to read the list of object type specifications. The OTT translates each type in the list.

The syntax for this parameter is

`intype`=<filename>

"INTYPE=" may be omitted if USERID and INTYPE are the first two parameters, in that order, and "USERID=" is omitted. If INTYPE is not specified, all types in the user's schema will be translated.

`OTT` username/password filename...

The INTYPE file can be thought of as a makefile for type declarations. It lists the types for which C struct declarations are needed. The format of the INTYPE file is described in section "Structure of the Intype File" on page 12-29.

If the file name on the command line or in the INTYPE file does not include an extension, a platform-specific extension such as "TYP" or ".typ" will be added.

#### outtype

The name of a file into which the OTT will write type information for all the object datatypes it processes. This includes all types explicitly named in the INTYPE file, and may include additional types that are translated because they are used in the declarations of other types that need to be translated. This file may be used as an INTYPE file in a future invocation of the OTT.

`outtype`=<filename>

If the INTYPE and OUTTYPE parameters refer to the same file, the new INTYPE information replaces the old information in the INTYPE file. This provides a convenient way for the same INTYPE file to be used repeatedly in the cycle of altering types, generating type declarations, editing source code, precompiling, compiling, and debugging.

OUTTYPE must be specified.

If the file name on the command line or in the INTYPE file does not include an extension, a platform-specific extension such as "TYP" or ".typ" will be added.

#### code

This is the desired host language for OTT output, which may be specified as CODE=C, CODE=KR_C, or CODE=ANSI_C. "CODE=C" is equivalent to "CODE=ANSI_C".

`CODE= C|KR_C|ANSI_C`

There is no default value for this parameter; it must be supplied.

#### initfile

The INITFILE parameter specifies the name of the file where the OTT-generated initialization file is to be written. The initialization function will not be generated if this parameter is omitted.

For Pro*C/C++ programs, the INITFILE is not necessary, because the SQLLIB run-time library performs the necessary initializations. An OCI program user must compile and link the INITFILE file(s), and must call the initialization function(s) when an environment handle is created.

If the file name of an INITFILE on the command line or in the INTYPE file does not include an extension, a platform-specific extension such as "C" or ".c" will be added.

`initfile`=<filename>

#### initfunc

The INITFUNC parameter is only used in OCI programs. It specifies the name of the initialization function generated by the OTT. If this parameter is omitted, the name of the initialization function is derived from the name of the INITFILE.

`initfunc`=<filename>

#### hfile

The name of the include (.h) file to be generated by the OTT for the declarations of types that are mentioned in the INTYPE file but whose include files are not specified there. This parameter is required unless the include file for each type is specified individually in the INTYPE file. This parameter is also required if a type not mentioned in the INTYPE file must be generated because other types require it, and these other types are declared in two or more different files.

If the file name of an HFILE on the command line or in the INTYPE file does
not include an extension, a platform-specific extension such as "H" or ".h" will be added.

`hfile`=<filename>

#### config

The CONFIG parameter specifies the name of the OTT configuration file, which lists commonly used parameter specifications. Parameter specifications are also read from a system configuration file in a platform-dependent location. All remaining parameter specifications must appear on the command line, or in the INTYPE file.

`config`=<filename>

  Note: A CONFIG parameter is not allowed in the CONFIG file.

#### errtype

If this parameter is supplied, a listing of the INTYPE file is written to the ERRTYPE file, along with all informational and error messages. Informational and error messages are sent to the standard output whether or not ERRTYPE is specified.

Essentially, the ERRTYPE file is a copy of the INTYPE file with error messages added. In most cases, an error message will include a pointer to the text which caused the error.

If the file name of an ERRTYPE on the command line or in the INTYPE file does not include an extension, a platform-specific extension such as "TLS" or ".tls" will be added.

`errtype`=<filename>

#### case

This parameter affects the case of certain C identifiers generated by the OTT. The possible values of CASE are SAME, LOWER, UPPER, and OPPOSITE. If CASE = SAME, the case of letters is not changed when converting database type and attribute names to C identifiers. If CASE=LOWER, all uppercase letters are converted to lowercase. If CASE=UPPER, all lowercase letters are converted to uppercase. If CASE=OPPOSITE, all uppercase letters are converted to lower-case, and vice-versa.

`CASE=[SAME|LOWER|UPPER|OPPOSITE]`

This option affects only those identifiers (attributes or types not explicitly listed) not mentioned in the INTYPE file. Case conversion takes place after a legal identifier has been generated.

  Note: The case of the C struct identifier for a type specifically mentioned in the INTYPE is the same as its case in the INTYPE file. For example, if the INTYPE file includes the following line

    TYPE Worker

then the OTT generates

    struct Worker {...};

On the other hand, if the INTYPE file were written as

    TYPE wOrKeR

the OTT generates

    struct wOrKeR {...};

following the case of the INTYPE file.

Case-insensitive SQL identifiers not mentioned in the INTYPE file will appear in upper case if CASE=SAME, and in lower case if CASE=OPPOSITE. A SQL identifier is case-insensitive if it was not quoted when it was declared.

#### schema_names

This option offers control in qualifying the database name of a type from the default schema with a schema name in the OUTTYPE file. The OUTTYPE file generated by the OTT contains information about the types processed by the OTT, including the type names.

See "SCHEMA_NAMES Usage" on page 12-33 for further information.

### Where OTT Parameters Can Appear

OTT parameters can appear on the command line, in a CONFIG file named on the command line, or both. Some parameters are also allowed in the INTYPE file.

The OTT is invoked as follows:

    OTT username/password <parameters>

If one of the parameters on the command line is

    config=<filename>

additional parameters are read from the configuration file `<filename>`.

In addition, parameters are also read from a default configuration file in a platform-dependent location. This file must exist, but can be empty. Parameters in a configuration file must appear one per line, with no whitespace on the line.

If the OTT is executed without any arguments, an on-line parameter reference is displayed.

The types for the OTT to translate are named in the file specified by the INTYPE parameter. The parameters CASE, INITFILE, INITFUNC, and HFILE may also appear in the INTYPE file. OUTTYPE files generated by the OTT include the CASE parameter, and include the INITFILE, and INITFUNC parameters if an initialization file was generated. The OUTTYPE file specifies the HFILE individually for each type.

The case of the OTT command is platform-dependent.

### Structure of the Intype File

The intype and outtype files list the types translated by the OTT, and provide all the information needed to determine how a type or attribute name is translated to a legal C identifier. These files contain one or more type specifications. These files also may contain specifications of the following options:

- CASE
- HFILE
- INITFILE
- INITFUNC

If the CASE, INITFILE, or INITFUNC options are present, they must precede any type specifications. If these options appear both on the command line and in the intype file, the value on the command line is used.

For an example of a simple user-defined intype file, and of the full outtype file that the OTT generates from it, see "The Outtype File" on page 12-16.

#### Intype File Type Specifications

A type specification in the INTYPE names an object datatype that is to be translated. A type specification in the OUTTYPE file names an object datatype that has been translated,

    TYPE PERSON AS PERSON
      VERSION = "$8.0"
      HFILE = demo.h
    The structure of a type specification is as follows:
    TYPE <type_name> [AS <type_identifier>]
    [VERSION [=] <version_string>]
    [HFILE [=] <hfile_name>]
    [TRANSLATE{<member_name> [AS <identifier>]}...]

    The syntax of  type_name is:
    [<schema_name>.]<type_name>

where schema_name is the name of the schema which owns the given object datatype, and type_name is the name of the type. The default schema is that of the user running the OTT. The default database is the local database.

The components of a type specification are described below.

- `<type_name>` is the name of an Oracle8 object datatype.
- `<type_identifier>` is the C identifier used to represent the type. If omitted, the default name mapping algorithm will be used.
- `<version_string>` is the version string of the type which was used when the code was generated by a previous invocation of the OTT. The version string is generated by the OTT and written to the OUTTYPE file, which may later be used as the INTYPE file when the OTT is later executed. The version string does not affect the OTT's operation, but will eventually be used to select which version of the object datatype should be used in the running program.
- `<type_identifier>` is the C identifier used to represent the type. If omitted, the default type mapping algorithm will be used. For further information, see "Default Name Mapping" on page 12-35.
- `<member_name>` is the name of an attribute (data member) which is to be translated to the following `<identifier>`.
- `<identifier`> is the C identifier used to represent the attribute in the user program. Identifiers may be specified in this way for any number of attributes. The default name mapping algorithm will be used for the attributes that are not mentioned.
- `<hfile_name>` is the name of the header file in which the declarations of the corresponding struct or class appears or will appear. If `<hfile name>` is omitted, the file named by the command-line HFILE parameter will be used if a declaration is generated.

An object datatype may need to be translated for one of two reasons:

- It appears in the INTYPE file.
- It is required to declare another type that must be translated.

If a type that is not mentioned explicitly is required by types declared in exactly one file, the translation of the required type is written to the same file(s) as the explicitly declared types that require it.

If a type that is not mentioned explicitly is required by types declared in two or more different files, the translation of the required type is written to the global HFILE file.

### Nested #include File Generation

Every HFILE generated by the OTT #includes other necessary files, and `#defines` a symbol constructed from the name of the file, which may be used to determine if the HFILE has already been included. Consider, for example, a database with the following types:

    create type px1 AS OBJECT (col1 number, col2 integer);
    create type px2 AS OBJECT (col1 px1);
    create type px3 AS OBJECT (col1 px1);

where the intype file contains:

    CASE=lower
    type pxl
      hfile tott95a.h
    type px3
      hfile tott95b.h

If we invoke the OTT with

    ott scott/tiger tott95i.typ outtype=tott95o.typ code=c

then it will generate the two following header files.

File tott95b.h is:

    #ifndef TOTT95B_ORACLE
    #define TOTT95B_ORACLE
    #ifndef OCI_ORACLE
    #include <oci.h>
    #endif
    #ifndef TOTT95A_ORACLE
    #include "tott95a.h"
    #endif
    typedef OCIRef px3_ref;
    struct px3
    {
       struct px1 col1;
    };
    typedef struct px3 px3;
    struct px3_ind
    {
       OCIInd _atomic;
       struct px1_ind col1
    };
    typedef struct px3_ind px3_ind;
    #endif

File tott95a.h is:

    #ifndef TOTT95A_ORACLE
    #define TOTT95A_ORACLE
    #ifndef OCI_ORACLE
    #include <oci.h>
    #endif
    typedef OCIRef px1_ref;
    struct px1
    {
       OCINumber col1;
       OCINumber col2;
    }
    typedef struct px1 px1;
    struct px1_ind
    {
       OCIInd _atomic;
       OCIInd col1;
       OCIInd col2;
    }
    typedef struct px1_ind px1_ind;
    #endif

In this file, the symbol TOTT95B_ORACLE is defined first so that the programmer may conditionally include tott95b.h without having to worry whether tott95b.h depends on the include file using the following construct:

    #ifndef TOTT95B_ORACLE
    #include "tott95b.h"
    #endif

Using this technique, the programmer may include tott95b.h from some file, say foo.h, without having to know whether some other file included by foo.h also includes tott95b.h.

After the definition of the symbol TOTT95B_ORACLE, the file oci.h is `#included`. Every HFILE generated by the OTT includes oci.h, which contains type and function declarations that the Pro*C/C++ or OCI programmer will find useful. This is the only case in which the OTT uses angle brackets in a `#include`.

Next, the file tott95a.h is included. This file is included because it contains the declaration of "`struct px1`", which tott95b.h requires. When the user's INTYPE file requests that type declarations be written to more than one file, the OTT determines which other files each HFILE must include, and will generate the necessary `#includes`.

Note that the OTT uses quotes in this #include. When a program including tott95b.h is compiled, the search for tott95a.h will begin where the source program was found, and will thereafter follow an implementation-defined search rule. If tott95a.h cannot be found in this way, a complete file name (e.g., a UNIX absolute pathname beginning with /) should be used in the INTYPE file to specify the location of tott95a.h.

### SCHEMA_NAMES Usage

This parameter affects whether the name of a type from the default schema to which the OTT is connected is qualified with a schema name in the OUTTYPE file.

The name of a type from a schema other that the default schema is always qualified with a schema name in the OUTTYPE file.

The schema name, or its absence, determines in which schema the type is found during program execution.

There are three settings:

- `schema_names`=ALWAYS (default)

  All type names in the OUTTYPE file are qualified with a schema name.

- `schema_names`=IF_NEEDED

  The type names in the OUTTYPE file that belong to the default schema are not qualified with a schema name. As always, type names belonging to other schemas are qualified with the schema name.

- `schema_names`=FROM_INTYPE

  A type mentioned in the INTYPE file is qualified with a schema name in the OUTTYPE file if, and only if, it was qualified with a schema name in the INTYPE file. A type in the default schema that is not mentioned in the INTYPE file but that has to be generated because of type dependencies will be written with a schema name only if the first type encountered by the OTT that depends on it was written with a schema name. However, a type that is not in the default schema to which the OTT is connected will always be written with an explicit schema name.

The OUTTYPE file generated by the OTT is an input parameter to Pro*C/C++. From the point of view of Pro*C/C++, it is the Pro*C/C++ INTYPE file. This file matches database type names to C struct names. This information is used at run-time to make sure that the correct database type is selected into the struct. If a type appears with a schema name in the OUTTYPE file (Pro*C/C++ INTYPE file), the type will be found in the named schema during program execution. If the type appears without a schema name, the type will be found in the default schema to which the program connects, which may be different from the default schema the OTT used.

##### An Example

If SCHEMA_NAMES is set to FROM_INTYPE, and the INTYPE file reads:

    TYPE Person

    TYPE david.Dept

    TYPE eric.Company

then the Pro*C/C++ application that uses the OTT-generated structs will use the types `sam.Company`, `david.Dept`, and `Person`. Using `Person` without a schema name refers to the `Person` type in the schema to which the application is connected.

If the OTT and the application both connect to schema `david`, the application will use the same type (`david.Person`) that the OTT used. If the OTT connected to schema `david` but the application connects to schema `jana`, the application will use the type `jana.Person`. This behavior is appropriate only if the same "`CREATE TYPE Person`" statement has been executed in schema `david` and schema `jana`.

On the other hand, the application will use type `david.Dept` regardless of to which schema the application is connected. If this is the behavior you want, be sure to include schema names with your type names in the INTYPE file.

In some cases, the OTT translates a type that the user did not explicitly name. For example, consider the following SQL declarations:

    CREATE TYPE Address AS OBJECT
    ( street    VARCHAR2(40),
        city      VARCHAR(30),
        state     CHAR(2),
        zip_code  CHAR(10) );

    CREATE TYPE Person AS OBJECT
    ( name      CHAR(20),
        age       NUMBER,
        addr      ADDRESS );

Now suppose that the OTT connects to schema `david`, SCHEMA_NAMES=FROM_INTYPE is specified, and the user's INTYPE files include either

    TYPE Person

or

    TYPE david.Person

but do not mention the type `david.Address`, which is used as a nested object type in type `david.Person`. If "`TYPE david.Person`" appeared in the INTYPE file, "`TYPE david.Person`" and "`TYPE david.Address`" will appear in the OUTTYPE file. If "`Type Person`" appeared in the INTYPE file, "`TYPE Person`" and "`TYPE Address`" will appear in the OUTTYPE file.

If the `david.Address` type is embedded in several types translated by the OTT, but is not explicitly mentioned in the INTYPE file, the decision of whether to use a schema name is made the first time the OTT encounters the embedded `david.Address` type. If, for some reason, the user wants type `david.Address` to have a schema name but does not want type `Person` to have one, the user should explicitly request

    TYPE      david.Address

in the INTYPE FILE.

The main point is that in the usual case in which each type is declared in a single schema, it is safest for the user to qualify all type names with schema names in the INTYPE file.

### Default Name Mapping

When the OTT creates a C identifier name for an object type or attribute, it translates the name from the database character set to a legal C identifier. First, the name is translated from the database character set to the character set used by the OTT. Next, if a translation of the resulting name is supplied in the INTYPE file, that translation is used. Otherwise, the OTT translates the name character-by-character to the compiler character set, applying the CASE option. This process is described in more detail below:

When the OTT reads the name of a database entity, the name is automatically translated from the database character set to the character set used by the OTT. In order for the OTT to read the name of the database entity successfully, all the characters of the name must be found in the OTT character set, although a character may have different encodings in the two character sets.

The easiest way to guarantee that the character set used by the OTT contains all the necessary characters is to make it the same as the database character set. Note, however, that the OTT character set must be a superset of the compiler character set. That is, if the compiler character set is 7-bit ASCII, the OTT character set must include 7-bit ASCII as a subset, and if the compiler character set is 7-bit EBCDIC, the OTT character set must include 7-bit EBCDIC as a subset. The user specifies the character set that the OTT uses by setting the NLS_LANG environment variable, or by some other platform-specific mechanism.

Once the OTT has read the name of a database entity, it translates the name from the character set used by the OTT to the compiler's character set. If a translation of the name appears in the INTYPE file, the OTT uses that translation.

Otherwise, the OTT attempts to translate the name as follows:

1. First, if the OTT character set is a multi-byte character set, all multi-byte characters in the name that have single-byte equivalents are converted to those single-byte equivalents.
2. Next, the name is converted from the OTT character set to the compiler character set. The compiler character set is a single-byte character set such as US7ASCII.
3. Finally, the case of letters is set according to the CASE option in effect, and any character that is not legal in a C identifier, or that has no translation in the compiler character set, is replaced by an underscore. If at least one character is replaced by an underscore, the OTT gives a warning message. If all the characters in a name are replaced by underscores, the OTT gives an error message.

Character-by-character name translation does not alter underscores, digits, or single-byte letters that appear in the compiler character set, so legal C identifiers are not altered.

Name translation may, for example, translate accented single-byte characters such as "o" with an umlaut or "a" with an accent grave to "o" or "a", and may translate a multi-byte letter to its single-byte equivalent. Name translation will typically fail if the name contains multi-byte characters that lack single-byte equivalents. In this case, the user must specify name translations in the INTYPE file.

The OTT will not detect a naming clash caused by two or more database identifiers being mapped to the same C name, nor will it detect a naming problem where a database identifier is mapped to a C keyword.

### Restrictions

The following restrictions exist which affect use of the OTT.

#### File Name Comparison

Currently, the OTT determines if two files are the same by comparing the file names provided by the user on the command line or in the INTYPE file. But one potential problem can occur when the OTT needs to know if two file names refer to the same file. For example, if the OTT-generated file `foo.h` requires a type declaration written to `foo1.h`, and another type declaration written to `/private/elias/foo1.h`, the OTT should generate one `#include` if the two files are the same, and two `#includes` if the files are different. In practice, though, it would conclude that the two files are different, and would generate two `#includes`, as follows:

    #ifndef FOO1_ORACLE
    #include "foo1.h"
    #endif
    #ifndef FOO1_ORACLE
    #include "/private/elias/foo1.h"
    #endif

If `foo1.h` and `/private/elias/foo1.h` are different files, only the first one will be included. If `foo1.h` and `/private/elias/foo1.h` are the same file, a redundant `#include` will be written.

Therefore, if a file is mentioned several times on the command line or in the INTYPE file, each mention of the file should use exactly the same file name.

Prev | Next
| Copyright © 1997 Oracle Corporation. All Rights Reserved. |
Library | Product | Contents | Index