United States

Compaq C

# Compaq C
User's Guide for OpenVMS Systems

Previous | Contents | Index

# Appendix C
Programming Tools

This appendix provides information on tools that you can use to develop and to refine your Compaq C programs. Some of the products described ship with the OpenVMS operating system; others must be purchased separately. The following products are described in this appendix:

- OpenVMS Debugger ( Section C.1)
- OpenVMS Text Processing Utility ( Section C.2)
- Language-Sensitive Editor and Source Code Analyzer ( Section C.3)
- CDD/Repository ( Section C.4)

# C.1 OpenVMS Debugger

A debugger is a tool to help you locate run-time errors quickly. It enables you to observe and manipulate the program's execution interactively, step by step, until you locate the point at which the program stopped working correctly.

The OpenVMS Debugger (provided with the OpenVMS operating system) is a symbolic debugger. You can refer to program locations by the symbols (names) you used for those locations in your program: the names of variables, routines, labels, and so on. You do not have to use virtual addresses to refer to memory locations.

If your program is written in more than one language, you can change from one language to another in the course of a debugging session. The current source language determines the format used for entering and displaying data, as well as other features that have language-specific settings (for example, comment characters, operators and operator precedence, and case sensitivity or insensitivity).

For information on the debugger, see the OpenVMS Debugger Manual.

The following sections provide language-specific information on the
OpenVMS Debugger.

## C.1.1 Compiling and Linking to Prepare for Debugging

The following example shows how to compile and link a Compaq C program (consisting of a single compilation unit named INVENTORY) so that you will be able to use the debugger:

    $ CC/DEBUG/NOOPTIMIZE INVENTORY
    $ LINK/DEBUG INVENTORY

The /DEBUG qualifier on the CC command causes the compiler to write the debug symbol records associated with INVENTORY.C into the object module, INVENTORY.OBJ. These records allow you to use the names of variables and other symbols declared in INVENTORY with debugger commands. (If your program has several compilation units, you must compile each unit that you want to debug with the /DEBUG qualifier.)

You should use the /NOOPTIMIZE qualifier when you compile in preparation for debugging. Without this qualifier, the resulting object code is optimized, which may cause the contents of some program locations to be inconsistent with what you might expect from the source code. (After the program has been debugged, you will probably want to recompile it without the /NOOPTIMIZE qualifier, because optimization might reduce a program's size and increase the execution speed.)

The /DEBUG qualifier on the LINK command causes the linker to include all symbol information that is contained in INVENTORY.OBJ in the executable image. The qualifier also causes the OpenVMS image activator to start the debugger at run time. (If your program has several object modules, you might need to specify other modules in the LINK command.)

## C.1.2 Starting and Terminating a Debugging Session

Before you invoke the debugger, enter the following command to check the current debugger configuration:

    $ SHOW LOGICAL DBG$PROCESS
    %SHOW-S-NOTRAN, no translation for logical name DBG$PROCESS

If DBG$PROCESS has a value other than undefined (as in the previous example) or DEFAULT, enter the following command to change this value:

    $ DEFINE DBG$PROCESS DEFAULT

Enter the DCL command RUN to invoke the debugger. The following message appears on your screen:

    $ RUN INVENTORY
                         OpenVMS DEBUG Version 6.n
    %DEBUG-I-INITIAL, language is C, module set to 'INVENTORY'
    DBG>

You can now enter debugger commands at the DBG> prompt. At this point, if you enter the GO command, program execution begins and continues until it is forced to pause or stop (for example, if the program prompts you for input, or an error occurs).

To interrupt a debugging session and return to the debugger prompt, press Ctrl/C. This is useful if, for example, your program loops or you want to interrupt a debugger command that is still in progress. For example:

    DBG> GO
        .
        .
        .
    (infinite loop)
    [Ctrl/C]
    Interrupt
    %DEBUG-W-ABORTED, command aborted by user request
    DBG>

The following message indicates that your program has completed successfully:

    %DEBUG-I-EXITSTATUS, is '%SYSTEM-S-NORMAL, normal successful completion'
    DBG>

To end a debugging session, enter the EXIT command at the DBG> prompt or press Ctrl/Z:

    DBG> EXIT
    $

## C.1.3 Notes on Compaq C Support

In general, the OpenVMS Debugger supports the data types and operators of
Compaq C and of the other debugger-supported languages. To get information on the supported data types and operators of any of the languages, enter the HELP LANGUAGE command at the DBG> prompt.

The following sections present Compaq C specific debugging examples.

### C.1.3.1 Debugger Command-Line Options

Compaq C provides a set of debugger options that you can specify to the /DEBUG qualifier to the CC command. These options alter the types of information that the compiler places in the object module for use by the OpenVMS Debugger. The debugger options include using traceback records, using the symbol table, and enabling the debugger to step into inline functions. For information about these options, see Section 1.3.4.

### C.1.3.2 Accessing Scalar Variables

The EXAMINE command displays scalar variables of any Compaq C data type. Reference scalar variables in the same case that you declare them, using the
Compaq C syntax for such references.

Example C-1 shows the Compaq C program SCALARS.C used in the examples that follow.

Example C-1 Debugging Sample Program SCALARS.C

    /*  SCALARS.C  This program defines a large number of          *
     *             variables to demonstrate the effect             *
     *             of the various STEP debugger commands.          */

    main()
    {
       static float light_speed;       /*  Define the variable.    */
       static double speed_power;
       static unsigned ui;
       static long li;
       static char ch;
       static enum primary { red, yellow, blue } color;
       static int *ptr;

       light_speed = 3.0e10;
       speed_power = 3.1234567890123456789e10;
       ui = -438394;
       li = 790374270;
       ch = 'A';
       color = blue;
       ptr = &li;
    }

The following debugging examples are based on executing SCALARS.EXE and show the commands used to access variables of scalar data type.

The debugger command SHOW SYMBOL/TYPE displays the data type of one variable:

    DBG> show symbol/type color
    data SCALARS\main\color
        enumeration type (primary, 3 elements), size: 4 bytes

The following debugging commands set a breakpoint before the end of the program and execute the program up to the breakpoint. The program initializes the variables declared in `main` :

    DBG> set break %line 22
    DBG> go
    break at SCALARS\main\%LINE 22
        22: }

The EXAMINE command displays the contents of the variables listed. The `char` variables are interpreted by the debugger as byte integers, not ASCII characters:

    DBG> examine li, ui, light_speed, speed_power, ch, color, *ptr
    SCALARS\main\li:        790374270
    SCALARS\main\ui:        4294528902
    SCALARS\main\light_speed:       3.0000001E+10
    SCALARS\main\speed_power:       31234567890.12346
    SCALARS\main\ch:        65
    SCALARS\main\color:     blue
    *SCALARS\main\ptr:       790374270

To display the contents of `ch` as a character, you must use the /ASCII qualifier:

    DBG> examine/ascii ch
    SCALARS\main\ch:      "A"

The DEPOSIT command loads the value single_quote> `z` ' in the variable `ch` ; the EXAMINE command shows that single_quote> `z` ' has replaced the previous contents of the variable `ch` . Again, use the /ASCII qualifier to translate the byte integer into its ASCII equivalent:

    DBG> deposit/ascii ch = 'z'
    DBG> examine/ascii ch
    SCALARS\main\ch:        "z"
    DBG>

### C.1.3.3 Accessing Arrays

With the EXAMINE command, you can look at the values in arrays using Compaq C syntax for array references. You can examine an entire array by giving the array identifier. You can examine individual elements of the array using the array operator ([ ]). Array elements can have any data type.

Consider the following declaration:

    int  arr[10];

This declares an array of 10 elements, `arr[0]` through `arr[9]` .

Example C-2 shows the Compaq C program ARRAY.C used in the examples that follow.

Example C-2 Debugging Sample Program ARRAY.C

    /*  ARRAY.C  This program increments an array to               *
     *           demonstrate the access of arrays in Compaq C.        */

    main()
    {
        int i;
        static int arr[10];
        for (i=0; i<10; i++)
              arr[i]=i;
    }

The examples that follow are based on executing ARRAY.EXE and show the commands used to access variable arrays.

The following commands set a breakpoint at the last line in the program and execute the program to that point:

    DBG> set br  %line 10
    DBG> go
    break at ARRAY\main\%LINE 10
        10: }

By specifying the variable identifier, you can look at the entire array:

    DBG> examine arr
    ARRAY\main\arr
        [0]:        0
        [1]:        1
        [2]:        2
        [3]:        3
        [4]:        4
        [5]:        5
        [6]:        6
        [7]:        7
        [8]:        8
        [9]:        9

You can examine individual elements of the array by using the bracket operator to specify the subscript of the element. Pressing Return (the debugger's address reference operator) in an EXAMINE command displays the next element of the array. Using the up-arrow address reference operator (^) displays the previous member of the array:

    DBG> examine arr[5]
    ARRAY\main\arr[5]:      5
    DBG> examine [Return]
    ARRAY\main\arr[6]:      6
    DBG> examine ^
    ARRAY\main\arr[5]:      5

### C.1.3.4 Accessing Character Strings

Character strings are implemented in Compaq C as null-terminated ASCII strings (ASCIZ strings). To examine and deposit data in an entire string, use the /ASCIZ qualifier (abbreviated /AZ) so that the debugger can interpret the end of the string properly. You can examine and deposit individual characters in the string using the C array subscripting operators ([ ]). When you examine and deposit individual characters, use the /ASCII qualifier.

Example C-3 shows the Compaq C program STRING.C used in the examples that follow.

Example C-3 Debugging Sample Program STRING.C

    /*  STRING.C  This program establishes a string to             *
     *            demonstrate the access of strings in Compaq C.      */

    main()
    {
       static char *s = "vaxie";
       static char **t = &s;
    }

The following examples are based on executing STRING.EXE and show the commands used to manipulate C strings.

The EXAMINE/AZ command displays the contents of the character string pointed to by `*s` and `**t` :

    DBG> step
    stepped to STRING\main\%LINE 8
        8: }
    DBG> examine/az  *s
    *STRING\main\s: "vaxie"
    DBG> examine/az  **t
    **STRING\main\t:        "vaxie"

The DEPOSIT/AZ command deposits a new ASCIZ string in the variable pointed to by `*s` . The EXAMINE/AZ command displays the new contents of the string:

    DBG> deposit/az  *s = "Compaq C"
    DBG> examine/az  *s,  **t
    *STRING\main\s: "Compaq C"
    **STRING\main\t:         "Compaq C"

You can use array subscripting to examine individual characters in the string and deposit new ASCII values at specific locations within the string. When accessing individual members of a string, use the /ASCII qualifier. A subsequent EXAMINE/AZ command shows the entire string containing the deposited value:

    DBG> examine/ascii s[3]
    [3]:    " "
    DBG> deposit/ascii s[3] = "-"
    DBG> examine/az *s, **t
    *STRING\main\s:    "DEC-C"
    **STRING\main\t:   "DEC-C"

### C.1.3.5 Accessing Structures and Unions

You can examine structures in their entirety or on a member-by-member basis, and deposit data into structures one member at a time.

To reference members of a structure or union, use the usual C syntax for such references. That is, if variable `p` is a pointer to a structure, you can reference member `y` of that structure with the expression `p ->y` . If variable `x` refers to the base of the storage allocated for a structure, you can refer to a member of that structure with the `x.y` expression.

The debugger uses the Compaq C type-checking rules that follow to reference members of a structure or union. For example, in the case of `x.y` , `y` need not be a member of `x` ; it is treated as an offset with a type. When such a reference is ambiguous---when there is more than one structure with a member `y` ---the debugger attempts to resolve the reference according to the rules that follow. The same rules for resolving the ambiguity of a reference to a member of a structure or union apply to both `x.y` and `p ->y` .

- If only one of the members, `y` , belongs in the structure or union, `x` , that is the one that is referenced.
- If only one of the members, `y` , is in the same scope as `x` , then that is the one that is referenced.

You can always give a path name with the reference to `x` to narrow the scope that is used and to resolve the ambiguity. The same path name is used to look up both `x` and `y` .

Example C-4 shows the Compaq C program STRUCT.C used in the examples that follow.

Example C-4 Debugging Sample Program STRUCT.C

    /*  STRUCT.C  This program defines a structure and union       *
     *            to demonstrate the access of structures and      *
     *            unions in Compaq C.                                 */

    main()
    {
       static struct
          {
             int im;
             float fm;
             char cm;
             unsigned bf : 3;
          }  sv,  *p;

       union
          {
             int im;
             float fm;
             char cm;
          }  uv;

       sv.im = -24;
       sv.fm = 3.0e10;
       sv.cm = 'a';
       sv.bf = 7;          /* Binary: 111 */

       p = &sv;

       uv.im = -24;
       uv.fm = 3.0e10;
       uv.cm = 'a';

    }

The following examples are based on executing STRUCT.EXE and show the commands used to access structures and unions.

The SHOW SYMBOL command shows the variables contained in the user-defined function main:

    DBG> show symbol  *  in main
    routine STRUCT\main
    data STRUCT\main\uv
    record component STRUCT\main\<generated_name_0002>.im
    record component STRUCT\main\<generated_name_0002>.fm
    record component STRUCT\main\<generated_name_0002>.cm
    type STRUCT\main\<generated_name_0002>
    data STRUCT\main\p
    data STRUCT\main\sv
    record component STRUCT\main\<generated_name_0001>.im
    record component STRUCT\main\<generated_name_0001>.fm
    record component STRUCT\main\<generated_name_0001>.cm
    record component STRUCT\main\<generated_name_0001>.bf
    type STRUCT\main\<generated_name_0001>

Set a breakpoint at line 29 and enter a GO command to initialize the variables declared in the structure `sv` :

    DBG> set break  %line 29
    DBG> go
    break at STRUCT\main\%LINE 29
        29:    uv.im = -24;

Use the EXAMINE command with the name of the structure to display all structure members. Note that `sv.cm` has the `char` data type, which is interpreted by the debugger as a byte integer. The debugger also displays the value of bit fields in decimal:

    DBG> examine sv
    STRUCT\main\sv
        im: -24
        fm: 3.0000001E+10
        cm: 97
        bf: 7

To display the ASCII representation of a `char` data type, use the /ASCII qualifier on the EXAMINE command. To display bit fields in their binary representation, use the /BINARY qualifier:

    DBG> examine/ascii sv.cm
    STRUCT\main\sv.cm:     "a"
    DBG> examine/binary sv.bf
    STRUCT\main\sv.bf:     111

You deposit data into a structure one member at a time. To deposit data into a member of type `char` , use the /ASCII qualifier and enclose the character in either single or double quotation marks. To deposit a new binary value in a bit field, use the %BIN keyword:

    DBG> deposit sv.im = 99
    DBG> deposit sv.fm = 3.14
    DBG> deposit/ascii sv.cm = 'z'
    DBG> deposit sv.bf = %BIN 010
    DBG> examine sv
    STRUCT\main\sv
        im: 99
        fm: 3.140000
        cm: 122
        bf: 2

You can also access members of structures (and unions) by pointer, as shown in `*p` and `p ->bf` :

    DBG> examine *p
    *STRUCT\main\p
        im: 99
        fm: 3.140000
        cm: 122
        bf: 2
    DBG> examine/binary p ->bf
    STRUCT\main\p ->bf:     010

A union contains only one member at a time, so the value for `uv.im` is the only valid value returned by the EXAMINE command; the other values are meaningless:

    DBG> step
    stepped to STRUCT\main\%LINE 30
        30:    uv.fm = 3.0e10;
    DBG> examine uv
    STRUCT\main\uv
        im: -24
        fm: -1.5485505E+38
        cm: -24

This series of STEP and EXAMINE commands shows the content of the union as the different members are assigned values:

    DBG> step
    stepped to STRUCT\main\%LINE 31
        31:    uv.cm = 'a';
    DBG> examine uv.fm
    STRUCT\main\uv.fm:     3.0000001E+10
    DBG> step
    stepped to STRUCT\main\%LINE 32
        33: }
    DBG> examine/ascii uv.cm
    STRUCT\main\uv.cm:     "a"

Example C-5 shows the Compaq C program ARSTRUCT.C used in the examples that follow.

Example C-5 Debugging Sample Program ARSTRUCT.C

    /*  ARSTRUCT.C  This program contains a structure definition   *
     *              and a for loop to demonstrate the debugger's   *
     *              support for Compaq C operators.          */

    main()
    {
       int   count,  i = 1;
       char  c = 'A';

       struct
          {
             int digit;
             char alpha;
          }  tbl[27], *p;

       for (count = 0; count <= 26; count++)
          {
             tbl[count].digit = i++;
             tbl[count].alpha = c++;
          }
    }

The following examples are based on executing ARSTRUCT.EXE and show the use of C expressions on the debugger command line.

Relational operators can be used in expressions (such as `count == 2` ) in a WHEN clause to set a conditional breakpoint:

    DBG> set  break  %line  20  when  (count == 2)
    DBG> go
    break at ARSTRUCT\main\%LINE 20
        20:       }

The first EVALUATE command that follows uses C syntax to refer to the address of a variable. It is equivalent to the second command, which uses the /ADDRESS qualifier to obtain the address of the variable. The addresses of these variables might not be the same every time you execute the program if you relink the program.

    DBG> evaluate  &tbl
    2146736881
    DBG> evaluate/address  tbl
    2146736881

Individual members of an aggregate can be evaluated; the debugger returns the value of the member:

    DBG> evaluate tbl[2].digit
    3

When you perform pointer arithmetic, the debugger displays a message indicating the scale factor that has been applied. It then returns the address resulting from the arithmetic operation. A subsequent EXAMINE command at that address returns the value of the variable:

    DBG> evaluate tbl + 4
    %DEBUG-I-SCALEADD, pointer addition: scale factor of 5 applied to
    right argument
    2146736901
    DBG> examine 2146736901
    ARSTRUCT\main\tbl[4].digit:     5

The EVALUATE command can perform arithmetic operations on program variables:

    DBG> evaluate tbl[4].digit * 2
    10

The EVALUATE command can also perform arithmetic calculations that may or may not be related to your program. In effect, this command can be used as a calculator that uses C syntax for arithmetic expressions:

    DBG> evaluate 7 % 3
    1

The debugger enters a message when you use an unsupported operator:

    DBG> evaluate count++
    %DEBUG-W-SIDEFFECT, operators with side effects not supported (++, --)

Previous | Next | Contents | Index

privacy and legal statement