Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ ctrace(CP) — OpenDesktop Software Development System 3.0.0

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

bfs(C)

ctype(S)

fclose(S)

printf(S)

setjmp(S)

signal(S)

string(S)

tail(C)


 ctrace(CP)                     6 January 1993                     ctrace(CP)


 Name

    ctrace - C program debugger

 Syntax

    ctrace [ options ] [ file ]

 Description

    The ctrace command allows you to follow the execution of a C program,
    statement-by-statement.  The effect is similar to executing a shell pro-
    cedure with the -x option.  ctrace reads the C program in file (or from
    standard input if you do not specify file), inserts statements to print
    the text of each executable statement and the values of all variables
    referenced or modified, and writes the modified program to standard out-
    put.  You must put the output of ctrace into a temporary file because
    cc(CP) does not allow the use of a pipe.  You then compile and execute
    this file.

    As each statement in the program executes it will be listed at the termi-
    nal, followed by the name and value of any variables referenced or modi-
    fied in the statement, followed by any output from the statement.  Loops
    in the trace output are detected and tracing is stopped until the loop is
    exited or a different sequence of statements within the loop is executed.
    A warning message is printed every 1000 times through the loop to help
    you detect infinite loops.  The trace output goes to the standard output
    so you can put it into a file for examination with an editor or the
    bfs(C) or tail(C) commands.

    The options commonly used are:

    -f functions  Trace only these functions.

    -v functions  Trace all but these functions.

    You may want to add to the default formats for printing variables.  Long
    and pointer variables are always printed as signed integers.  Pointers to
    character arrays are also printed as strings if appropriate.  Char,
    short, and int variables are also printed as signed integers and, if
    appropriate, as characters.  Double variables are printed as floating
    point numbers in scientific notation.

    String arguments to the string(S) functions and return values from
    fgets(S), gets(S), and sprintf(S) are printed as strings.  You can
    request that variables be printed in additional formats, if appropriate,
    with these options:

    -o     Octal


    -x     Hexadecimal


    -u     Unsigned


    -e     Floating point

    These options are used only in special circumstances:

    -l n   Check n consecutively executed statements for looping trace out-
           put, instead of the default of 20.  Use 0 to get all the trace
           output from loops.

    -s     Suppress redundant trace output from simple assignment statements
           and string copy function calls.  This option can hide a bug caused
           by use of the ``='' operator in place of the ``=='' operator.

    -t n   Trace n variables per statement instead of the default of 10 (the
           maximum number is 20).  The ``Diagnostics'' section explains when
           to use this option.

    -P     Run the C preprocessor on the input before tracing it.  You can
           also use the -D, -I, and -U cpp(CP) options.

    These options are used to tailor the run-time trace package when the
    traced program will run in a non-UNIX type environment:

    -b     Use only basic functions in the trace code, that is, those in
           ctype(S), printf(S), and string(S).  These are usually available
           even in cross-compilers for microprocessors.  In particular, this
           option is needed when the traced program runs under an operating
           system that does not have signal(S), fflush(S), longjmp(S), or
           setjmp(S).

    -p string
           Change the trace print function from the default of printf(.  For
           example, fprintf(stderr, would send the trace to standard error
           output.

    -r f   Use file f in place of the runtime.c trace function package.  This
           lets you change the entire print function, instead of just the
           name and leading arguments (see the -p option).

 Example

    If the file lc.c contains this C program:

        1 #include <stdio.h>
        2 main()        /* count lines in input */
        3 {
        4         int c, nl;
        5
        6         nl = 0;
        7         while ((c = getchar()) != EOF)
        8                 if (c = '\n')
        9                         ++nl;
       10         printf("%d\n", nl);
       11 }

    And you enter these commands and test data:

    cc lc.c
    a.out
    1
    <Ctrl>-d

    the program will be compiled and executed.  The output of the program
    will be the number 2, which is not correct because there is only one line
    in the test data.  The error in this program is common, but subtle.  If
    you invoke ctrace with these commands:


    ctrace lc.c >temp.c
    cc temp.c
    a.out

    the output will be:

        2 main()
        6         nl = 0;
                   /* nl == 0 */
        7         while ((c = getchar()) != EOF)


    The program is now waiting for input.  If you enter the same test data as
    before, the output will be:

                  /* c == 49 or '1' or "text" */
        8                 if (c = '\n')
                           /* c == 10 or '\n' */
        9                         ++nl;
                                  /* nl == 1 */
        7         while ((c = getchar()) != EOF)
                  /* c == 10 or '\n' */
        8                 if (c = '\n')
                           /* c == 10 or '\n' */
        9                         ++nl;
                                  /* nl == 2 */
        7         /* repeating */


    If you now enter an end-of-file character (<Ctrl>-D) the final output
    will be:

             /* repeated < 1 time */
           7     while ((c = getchar()) != EOF)
                 /* c == -1 */
          10     printf ("%d0, nl);
                 /* nl == 2 */2
             /* return */


    Note that the program output printed at the end of the trace line for the
    nl variable.  Also note the return comment added by ctrace at the end of
    the trace output.  This shows the implicit return at the terminating
    brace in the function.

    The trace output shows that variable c is assigned the value '1' in line
    7, but in line 8 it has the value '\n'.  Once your attention is drawn to
    this if statement, you will probably realize that you used the assignment
    operator (``='') in place of the equality operator (``=='').  You can
    easily miss this error during code reading.

 Execution-Time trace control

    The default operation for ctrace is to trace the entire program file,
    unless you use the -f or -v options to trace specific functions.  This
    does not give you statement-by-statement control of the tracing, nor does
    it let you turn the tracing off and on when executing the traced program.

    You can do both of these by adding ctroff() and ctron() function calls to
    your program to turn the tracing off and on, respectively, at execution
    time.  Thus, you can code arbitrarily complex criteria for trace control
    with if statements, and you can even conditionally include this code
    because ctrace defines the CTRACE preprocessor variable.  For example:

       #ifdef CTRACE
               if (c == '!' && i > 1000)
                       ctron();
       #endif


    You can also call these functions from sdb(CP) if you compile with the -g
    option.  For example, to trace all but lines 7 to 10 in the main func-
    tion, enter:

       sdb a.out
       main:7b ctroff()
       main:11b ctron()
       r

    You can also turn the trace off and on by setting static variable tr_ct_
    to 0 and 1, respectively.  This is useful if you are using a debugger
    that cannot call these functions directly.

 Files


    /usr/lib/ctrace/runtime.c Run-time trace package.

 Diagnostics

    This section contains diagnostic messages from both ctrace and cc(CP),
    since the traced code often gets some cc warning messages.  You can get
    cc error messages in some rare cases, all of which can be avoided.

    ctrace diagnostics

    Warning: some variables are not traced in this statement
       Only 10 variables are traced in a statement to prevent the C compiler
       ``out of tree space; simplify expression'' error.  Use the -t option
       to increase this number.

    Warning: statement too long to trace
       This statement is over 400 characters long.  Make sure that you are
       using tabs to indent your code, not spaces.

    Cannot handle preprocessor code, use -P option
       This is usually caused by #ifdef/#endif preprocessor statements in the
       middle of a C statement, or by a semicolon at the end of a #define
       preprocessor statement.

    'if ... else if' sequence too long
       Split the sequence by removing an else from the middle.

    Possible syntax error, try -P option
       Use the -P option to preprocess the ctrace input, along with any
       appropriate -D, -I, and -U preprocessor options.  If you still get the
       error message, check the ``Warnings'' section below.

    cc diagnostics

    Warning: illegal combination of pointer and integer
    Warning: statement not reached
    Warning: sizeof returns 0
       Ignore these messages.

    Compiler takes size of function
       See the ctrace ``possible syntax error'' message above.

    yacc stack overflow
       See the ctrace ``'if ... else if' sequence too long'' message above.

    Out of tree space; simplify expression
       Use the -t option to reduce the number of traced variables per state-
       ment from the default of 10.  Ignore the ``ctrace: too many variables
       to trace'' warnings you will now get.

    Redeclaration of signal
       Either correct this declaration of signal(S), or remove it and
       #include <signal.h>.

 Warnings

    You will get a ctrace syntax error if you omit the semicolon at the end
    of the last element declaration in a structure or union, just before the
    right brace (}).  This is optional in some C compilers.

    Defining a function with the same name as a system function may cause a
    syntax error if the number of arguments is changed.  Just use a different
    name.

    The ctrace command assumes that BADMAG is a preprocessor macro, and that
    EOF and NULL are #defined constants.  Declaring any of these to be vari-
    ables, for example, "int EOF;", will cause a syntax error.

    This utility does not support code containing function prototypes.

 Notes

    The ctrace command does not know about the components of aggregates like
    structures, unions, and arrays.  It cannot choose a format to print all
    the components of an aggregate when an assignment is made to the entire
    aggregate.  ctrace may choose to print the address of an aggregate or use
    the wrong format (for example, 3.149050e-311 for a structure with two
    integer members) when printing the value of an aggregate.

    Pointer values are always treated as pointers to character strings.

    The loop trace output elimination is done separately for each file of a
    multifile program.  This can result in functions called from a loop still
    being traced, or the elimination of trace output from one function in a
    file until another in the same file is called.

 See also

    bfs(C), ctype(S), fclose(S), printf(S), setjmp(S), signal(S), string(S),
    tail(C)


Typewritten Software • bear@typewritten.org • Edmonds, WA 98026